2014-05-13 235 views
1

运行Thrift服务器时,有必要处理客户端意外断开连接的情况。这可能发生在服务器正在处理RPC时。如果服务器有阻塞调用,这通常用于挂起操作以通知客户端异步事件,这并不罕见。无论如何,在任何服务器上都可能发生并且确实发生这种情况,并且经常需要清理。Thrift服务器:检测客户端断开连接(C++库)

幸运的是,Thrift提供了TServerEventHandler类来挂接连接/断开回调。这用于使用C++库和命名管道传输的先前版本的Thrift(0.8,我相信)。然而,在Thrift 0.9.1中,当客户端连接时,createContext()和deleteContext()回调都会立即触发。两者都不会触发客户端断开连接。有没有新的方法来检测客户端断开连接?

代码片段:

//============================================================================ 
//Code snippet where the server is instantiated and started. This may 
//or may not be syntactically correct. 
//The event handler class is derived from TServerEventHandler. 
// 
{ 
    boost::shared_ptr<MyHandler> handler(new MyHandler()); 
    boost::shared_ptr<TProcessor> processor(new MyProcessor(handler)); 
    boost::shared_ptr<TServerTransport> serverTransport(new TPipeServer("MyPipeName")); 
    boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); 
    boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 

    boost::shared_ptr<TServer> server(new TSimpleServer(processor, transport, tfactory, pfactory)); 
    boost::shared_ptr<SampleEventHandler> EventHandler(new SampleEventHandler()); 

    server->setServerEventHandler(EventHandler); 
    server->serve(); 
} 

//============================================================================ 
//Sample event callbacks triggered by the server when something interesting 
//happens with the client. 
//Create an overload of TServerEventHandler specific to your needs and 
//implement the necessary methods. 
// 
class SampleEventHandler : public server::TServerEventHandler { 
public: 
    SampleEventHandler() : 
     NumClients_(0) //Initialize example member 
    {} 

    //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(boost::shared_ptr<protocol::TProtocol> input, boost::shared_ptr<protocol::TProtocol> output) 
    { 
     printf("SampleEventHandler callback: Client connected (total %d)\n", ++NumClients_); 
     return NULL; 
    } 

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

    //Called when a client is about to call the processor - 
    //virtual void processContext(void* serverContext, 
    boost::shared_ptr<TTransport> transport) {} 

protected: 
    uint32_t NumClients_; //Example member 
}; 

回答

1

如果的createContext()和deleteContext()都被称为在客户端连接,而不断开客户端,这是一个错误,应该在旧货JIRA所造成的问题。

+0

好点。我忘记提到的是,连接客户端是C#。也许C#命名为管道传输是奇怪的。 – pmont

+0

可能是,命名管道目前有相当稀疏的测试覆盖率。另外值得注意的是,TServerEventHandler方法可以在一些需要同步诸如NumClients_等资源的多线程服务器中同时调用。 – codeSF

相关问题