2013-01-31 165 views
9

我开始一个新项目,同时刚刚发现了Poco Library,我发现它非常棒。不过,我有点迷路,因为例子并不多。Poco :: Net服务器和客户端TCP连接事件处理程序

我有一个ServerApplication-> TCPServer-> ServerSocket + TCPServerConnectionFactory-> TCPServerconnection方法,如示例所示。我按照指示继承PocoNet课程。现在我可以运行我的服务器作为服务,&接收传入的连接。

我想对以下事件进行事件处理:在每个连接(或每个客户端)的基础上处理事件,例如可在客户端套接字上读取的数据,在客户端套接字上发生错误(断开连接或超时),在客户端套接字上发送没有错误的数据。

我该如何去做呢? 是Poco/Foundation/Events我在找什么,或者有一些机制在Poco :: Net中实现?

我已经看到了Poco :: Net :: NetExpections,但是当netcat连接关闭时,它们似乎不会出现在我的TCPServerConnection派生类中。

回答

9

我最终什么事是一种使用不同的方法,因为TCPSERVER是一个不同的野兽一起。在发布here的示例之后,我结束了一个继承自ServerApplication的类以及一个实质上连接处理程序SocketReactor构成的类。

Deamonizer头:

class Daemon : public ServerApplication 
{ 
    public: 
    Daemon(); 
    /// @Brief The main loop of the daemon, everything must take place here 
    int main(); 
}; 

Deamonizer实现:

int Daemon::main() 
{ 
    // Server Socket 
    ServerSocket svs(2222); 
    // Reactor-Notifier 
    SocketReactor reactor; 
    Poco::Timespan timeout(2000000); // 2Sec 
    reactor.setTimeout(timeout); 
    // Server-Acceptor 
    SocketAcceptor<ConnectionHandler> acceptor(svs, reactor); 
    // Threaded Reactor 
    Thread thread; 
    thread.start(reactor); 
    // Wait for CTRL+C 
    waitForTerminationRequest(); 
    // Stop Reactor 
    reactor.stop(); 
    thread.join(); 
    return Application::EXIT_OK; 
} 

处理程序类可以是任何东西,只要它具有符合构造函数(请参阅本波科:: NET文档)。 在我的情况,头看起来是这样的:

class ConnectionHandler 
{ 
    public: 

    /** 
    * @Brief Constructor of the Connection Handler 
    * @Note Each object is unique to an accepted connection 
    * @Param SteamSocket is the socket accepting the connections 
    * @See SocketAcceptor http://pocoproject.org/docs/Poco.Net.SocketAcceptor.html 
    * @Param SocketReactor is the reacting engine (threaded) which creates notifications about the socket 
    */ 
    ConnectionHandler(StreamSocket &, SocketReactor &); 

    /** 
    * @Brief Destructor 
    */ 
    ~ConnectionHandler(); 

    /** 
    * @Brief Event Handler when Socket becomes Readable, i.e: there is data waiting to be read 
    */ 
    void onSocketReadable(const AutoPtr<ReadableNotification>& pNf); 

    /** 
    * @Brief Event Handler when Socket was written, i.e: confirmation of data sent away (not received by client) 
    */ 
    void onSocketWritable(const AutoPtr<WritableNotification>& pNf); 

    /** 
    * @Brief Event Handler when Socket was shutdown on the remote/peer side 
    */ 
    void onSocketShutdown(const AutoPtr<ShutdownNotification>& pNf); 

    /** 
    * @Brief Event Handler when Socket throws an error 
    */ 
    void onSocketError(const AutoPtr<ErrorNotification>& pNf); 

    /** 
    * @Brief Event Handler when Socket times-out 
    */ 
    void onSocketTimeout(const AutoPtr<TimeoutNotification>& pNf); 

    private: 

    /** 
    * @Brief Read bytes from the socket, depending on available bytes on socket 
    */ 
    void readBytes(); 

    /** 
    * @Brief Send message to the socket 
    * @Param std::string is the message (null terminated) 
    */ 
    void sendMessage(std::string); 

    /// Stream Socket 
    StreamSocket _socket; 

    /// Socket Reactor-Notifier 
    SocketReactor& _reactor; 

    /// Received Data Buffer 
    std::vector<char *> in_buffer; 
}; 

你如何实现处理是你的,前提是你需要做的是注册类方法,它处理事件,像这样的唯一的事情:

_reactor.addEventHandler(_socket,NObserver<ConnectionHandler, ReadableNotification>(*this, &ConnectionHandler::onSocketReadable)); 
    _reactor.addEventHandler(_socket,NObserver<ConnectionHandler, ShutdownNotification>(*this, &ConnectionHandler::onSocketShutdown)); 
    _reactor.addEventHandler(_socket,NObserver<ConnectionHandler, ErrorNotification>(*this, &ConnectionHandler::onSocketError)); 
    _reactor.addEventHandler(_socket,NObserver<ConnectionHandler, TimeoutNotification>(*this, &ConnectionHandler::onSocketTimeout)); 

总而言之,两个类,几行代码,简单而干净。绝对开始爱Poco图书馆! :)

+0

尼斯反应堆:)谢谢亚历克斯 –

8

试试这个:

#include <iostream> 
#include "Poco/Net/TCPServer.h" 
#include "Poco/Net/TCPServerParams.h" 
#include "Poco/Net/TCPServerConnectionFactory.h" 
#include "Poco/Net/TCPServerConnection.h" 
#include "Poco/Net/Socket.h" 
using namespace std; 

class newConnection: public Poco::Net::TCPServerConnection { 
public: 
    newConnection(const Poco::Net::StreamSocket& s) : 
     Poco::Net::TCPServerConnection(s) { 
    } 

    void run() { 
     cout << "New connection from: " << socket().peerAddress().host().toString() << endl << flush; 
     bool isOpen = true; 
     Poco::Timespan timeOut(10,0); 
     unsigned char incommingBuffer[1000]; 
     while(isOpen){ 
      if (socket().poll(timeOut,Poco::Net::Socket::SELECT_READ) == false){ 
       cout << "TIMEOUT!" << endl << flush; 
      } 
      else{ 
       cout << "RX EVENT!!! ---> " << flush; 
       int nBytes = -1; 

       try { 
        nBytes = socket().receiveBytes(incommingBuffer, sizeof(incommingBuffer)); 
       } 
       catch (Poco::Exception& exc) { 
        //Handle your network errors. 
        cerr << "Network error: " << exc.displayText() << endl; 
        isOpen = false; 
       } 


       if (nBytes==0){ 
        cout << "Client closes connection!" << endl << flush; 
        isOpen = false; 
       } 
       else{ 
        cout << "Receiving nBytes: " << nBytes << endl << flush; 
       } 
      } 
     } 
     cout << "Connection finished!" << endl << flush; 
    } 
}; 

int main(int argc, char** argv) { 

    //Create a server socket to listen. 
    Poco::Net::ServerSocket svs(1234); 

    //Configure some server params. 
    Poco::Net::TCPServerParams* pParams = new Poco::Net::TCPServerParams(); 
    pParams->setMaxThreads(4); 
    pParams->setMaxQueued(4); 
    pParams->setThreadIdleTime(100); 

    //Create your server 
    Poco::Net::TCPServer myServer(new Poco::Net::TCPServerConnectionFactoryImpl<newConnection>(), svs, pParams); 
    myServer.start(); 

    while(1); 

    return 0; 
} 
+0

谢谢你的答复塞萨尔,但这并没有回答这个问题。你的例子只是接受连接,而我所要求的是一个select或(e)轮询或事件处理程序在接受连接传入数据,发生的错误,等等。 –

+0

完整的例子包括连接,超时,网络错误等。 .. –

+0

再次,非常感谢:) –