我正在尝试使用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如何能够跟踪客户端连接到服务器的位置?
答案 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;
}