mercredi 27 décembre 2017

Apache thrift multi client server

I am writing simple chat in Qt + Apache Thrift but right now I need to face a problem with connecting multiple clients. On first sight everything looks good and I cannot find where the problem is.

Here is my server main.cpp:

int main(int argc, char **argv) 
{
    int port = 9090;

    ::apache::thrift::stdcxx::shared_ptr<UsersStorageHandler> handler(new UsersStorageHandler());
    ::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new UsersStorageProcessor(handler));
    ::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    ::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    ::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);

    std::cout << "Users server started..." << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    server.serve();

    return 0;
}

Here is my server handler.h:

class UsersStorageHandler : virtual public UsersStorageIf
{
public:
    UsersStorageHandler();
    int32_t subscribeUser(const std::string& username);
    void unsubscribeUser(const int32_t userID);

private:
    Users users;
};

Here is my server handler.cpp:

UsersStorageHandler::UsersStorageHandler()
{
    srand(time(NULL));
}

int32_t UsersStorageHandler::subscribeUser(const std::string &username)
{
    ++idGenerator;

    assert(username != "");

    User user;
    user.userId  = idGenerator;
    user.username = username;
    user.colorR = (rand() % 255) + 0;
    user.colorG = (rand() % 255) + 0;
    user.colorB = (rand() % 255) + 0;
    user.colorA = 0;

    users[idGenerator] = user;

    std::cout << "NEW USER CONNECTED" << std::endl;
    std::cout << "==================" << std::endl;
    std::cout << "Username:\t" << user.username << std::endl;
    std::cout << "User ID:\t" << user.userId << std::endl;
    std::cout << "User R:\t" << user.colorR << std::endl;
    std::cout << "User G:\t" << user.colorG << std::endl;
    std::cout << "User B:\t" << user.colorB << std::endl;
    std::cout << "User A:\t" << user.colorA << std::endl;
    std::cout << "==================" << std::endl;
    std::cout << "CURRENT USERS COUNT:\t" << users.size() << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    /*
     * SEND TO CLIENT INFO ABOUT NEW USER HERE
     */

    return idGenerator;
}

void UsersStorageHandler::unsubscribeUser(const int32_t userID)
{
    auto index = users.find(userID);

    assert(index != users.end());

    users.erase(index);

    std::cout << "USER DISCONNECTED" << std::endl;
    std::cout << "=================" << std::endl;
    std::cout << "USER WITH ID " << userID << " ERASED" << std::endl;
    std::cout << "USERS COUNT:\t" << users.size() << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    /*
     * SEND TO CLIENT INFO ABOUT NEW USER HERE
     */
}

And right here is a method for connect to the server in client app:

void MainWindow::connectToServers(const std::string &ip, const uint32_t &port, const std::string &nick)
{
    m_usersServerIP = ip;
    m_usersServerPort = port;

    try
    {
        ::apache::thrift::stdcxx::shared_ptr<TTransport> socket(new TSocket(m_usersServerIP, m_usersServerPort));
        ::apache::thrift::stdcxx::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
        ::apache::thrift::stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));

        m_usersServerClient = std::make_shared<UsersStorageClient>(protocol);
        transport->open();

        m_clientID = m_usersServerClient.get()->subscribeUser(nick);

        QMessageBox::information(this, "Connected",
                             "You are connected "
                             "with users server");

        createAndRegisterUsersServerReactor();

        activateChatScreen();

    }
    catch (const std::exception &e)
    {
        qDebug() << e.what();
    }

    qDebug() << "ID FROM SERVER:\t" << m_clientID;
}

As far as I checked right now it is working like this: Created two instances of client app. In one instance fill nickname, ip, port and clicked connect (connectToServers method). Client connected. In another instance done the same but after clicked connected ... nothing happens. App freezes at this line:

m_clientID = m_usersServerClient.get()->subscribeUser(nick);

After closing first client, second one connects to the server.

Aucun commentaire:

Enregistrer un commentaire