与Thrift“跟踪”连接

时间:2010-04-14 19:14:30

标签: c++ rpc thrift

我正在尝试使用Thrift创建游戏,以便客户端是玩家,服务器管理板,就像this一样。但是,我无法弄清楚Facebook的Thrift服务器如何“跟踪”用户,即在their service上呼叫attack()时,我不必再次识别自己。

根据生成的服务器存根建议的内容,无法执行此操作:

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<ConnectFourHandler> handler(new ConnectFourHandler());
  shared_ptr<TProcessor> processor(new ConnectFourProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

在该示例中,只为服务器创建了一个处理程序,服务器接受连接。

如果每个服务器只通过一个处理程序路由所有请求,Facebook如何能够跟踪客户端连接到服务器的位置?

2 个答案:

答案 0 :(得分:0)

试试server.setServerEventHandler。它会在新客户端连接时调用您的代码,使您有机会创建特定于连接的上下文对象。

答案 1 :(得分:0)

由于节俭为每个连接使用唯一的线程,因此可以使用线程ID将两者链接在一起。据我所知,没有办法做到节俭。同时,如果thrift将上下文字段传递给每个处理程序函数,则是可能的。

以下是使用线程ID的示例:

#include <map>
#include <thread>

typedef struct {
    // you would put your connection specific variables here
} ConnectionContext;

// You could reverse these types if you had more than one
// context per thrift connection, eg. your service involved opening
// or connecting to more than one thing per thrift connection
std::map<std::thread::id, ConnectionContext> threadContextMap;

class OurEventHandler : public server::TServerEventHandler {
public:
OurEventHandler() :
    NumClients_(0)
{}

//Called before the server begins -
//virtual void preServe() {}

//createContext may return a user-defined context to aid in cleaning
//up client connections upon disconnection. This example dispenses
//with contextual information and returns NULL.
virtual void* createContext(shared_ptr<protocol::TProtocol> input, 
shared_ptr<protocol::TProtocol> output)
{
    printf("Client connected (total %d)\n", ++NumClients_);

    auto this_id = std::this_thread::get_id();
    std::cout << "connected thread " << this_id << std::endl;

    return NULL;
}

//Called when an client has disconnected, either naturally or by error.
virtual void deleteContext(void* serverContext, 
shared_ptr<protocol::TProtocol>input, shared_ptr<protocol::TProtocol>output)
{
    printf("Client disconnected (total %d)\n", --NumClients_);

    auto this_id = std::this_thread::get_id();
    std::cout << "disconnected thread " << this_id << std::endl;

    auto context = threadContextMap[this_id];

    // TODO: Perform your context specific cleanup code here
}

protected:
    uint32_t NumClients_;
};


class yourRpcHandler : virtual public service_rpcIf
{
public:
    yourRpcHandler() :
    {
        // Your initialization goes here
    }

    void SomeMethod()
    {
        auto context = threadContextMap[std::this_thread::get_id()];

        // TODO: use the context as you see fit
    }
};

int main(int argc, char **argv)
{
    int port = 9090;
    printf("Listening on port %d\n", port);

    auto rpcHandler = new yourRpcHandler();
    shared_ptr<yourRpcHandler> handler(rpcHandler);
    shared_ptr<TProcessor> processor(new yourRpcProcessor(handler));
    shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
    shared_ptr<OurEventHandler> EventHandler(new OurEventHandler());

    server.setServerEventHandler(EventHandler);
    server.serve();
    return 0;
}