【问题标题】:Apache thrift multi client serverApache Thrift 多客户端服务器
【发布时间】:2018-06-08 11:44:27
【问题描述】:

我正在使用 Qt + Apache Thrift 编写简单的聊天,但现在我需要面对连接多个客户端的问题。乍一看,一切看起来都很好,但我找不到问题所在。

这是我的服务器 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;
}

这是我的服务器 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;
};

这是我的服务器 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
     */
}

这是在客户端应用程序中连接到服务器的方法:

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;
}

据我现在检查,它的工作方式如下: 创建了两个客户端应用程序实例。在一个实例中填写昵称、ip、端口并单击连接(connectToServers 方法)。客户端已连接。在另一个例子中做了同样的事情,但点击连接后......什么也没有发生。应用程序在此行冻结:

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

关闭第一个客户端后,第二个连接到服务器。

【问题讨论】:

    标签: apache qt c++11 thrift thrift-protocol


    【解决方案1】:

    TSimplerServer 支持单个连接。您应该尝试使用 TThreadedServer 来支持多个并发客户端。

    【讨论】:

      【解决方案2】:

      正如克里斯上面提到的那样,要么创建一个线程服务器来同时处理多个请求。对我来说,我创建了一个如下所示的非阻塞服务器,以便能够以异步方式为多个客户端提供松散耦合服务。

      public static void start(dataClass configData, String env, int port) throws TTransportException {
      
          TNonblockingServerTransport transport = new TNonblockingServerSocket(port);
          TNonblockingServer.Args nBlockServer = new TNonblockingServer.Args(transport);
      
          ccmProviderServiceImpl impl = new ccmProviderServiceImpl(configData, env);
          Processor<ccmProviderServiceImpl> processor = new ccmProviderService.Processor<>(impl);
      
          TServer server = new TNonblockingServer(nBlockServer.processor(processor));
      
          //custom event handling for tracking
          ccmServerEventHandler cse = new ccmServerEventHandler();
          server.setServerEventHandler(cse);
      
          server.serve();
      }
      

      【讨论】:

        猜你喜欢
        • 2017-07-23
        • 2017-08-20
        • 2011-01-31
        • 2012-05-23
        • 1970-01-01
        • 2014-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多