2013-01-31 56 views
9

Tôi đang bắt đầu một dự án mới và đồng thời vừa khám phá Thư viện Poco, điều mà tôi thấy tuyệt vời. Tuy nhiên tôi là một chút bị mất, như ví dụ không phải là rất nhiều.Poco :: Trình xử lý sự kiện kết nối TCP Server & máy khách Net

Tôi có phương pháp tiếp cận ServerApplication-> TCPServer-> ServerSocket + TCPServerConnectionFactory-> TCPServerconnection như được chỉ ra trong ví dụ. Tôi đang kế thừa từ các lớp PocoNet theo hướng dẫn. Ngay bây giờ tôi có thể chạy máy chủ của tôi như một dịch vụ, & nhận các kết nối đến.

Tôi muốn thực hiện một phương pháp xử lý sự kiện như sau: trên cơ sở mỗi kết nối (hoặc mỗi khách hàng), xử lý các sự kiện như dữ liệu sẵn có để đọc trên ổ cắm máy khách, lỗi xảy ra trên ổ cắm máy khách (ngắt kết nối hoặc timeout), gửi dữ liệu mà không có lỗi trên ổ cắm máy khách.

Tôi làm cách nào để thực hiện? Có phải Poco/Foundation/Events mà tôi đang tìm kiếm hay có một số cơ chế được triển khai trong Poco :: Net không?

Tôi đã thấy Poco :: Net :: NetExpections nhưng chúng dường như không được ném vào lớp dẫn xuất TCPServerConnection của tôi khi kết nối netcat đóng.

Trả lời

9

gì tôi đã kết thúc sử dụng là một cách tiếp cận khác nhau như TCPServer là một con thú khác nhau hoàn toàn. Theo ví dụ được đăng here Tôi đã kết thúc với một lớp kế thừa từ ServerApplication và một lớp về cơ bản là kết nối handler bởi một SocketReactor.

Deamonizer tiêu đề:

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

Deamonizer thực hiện:

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

Lớp xử lý có thể được bất cứ điều gì miễn là nó có một Constructor phù hợp (xem tài liệu Poco :: Net cho việc này). Trong trường hợp của tôi header trông như thế này:

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

Làm thế nào bạn thực hiện xử lý là tùy thuộc vào bạn, với điều kiện là điều duy nhất mà bạn cần phải làm là đăng ký phương pháp lớp học mà xử lý các sự kiện như vậy:

_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)); 

Tất cả trong tất cả, hai lớp, một vài dòng mã, đơn giản và rõ ràng. Tuyệt đối bắt đầu yêu thư viện Poco! :)

+0

Lò phản ứng tốt :) Cảm ơn Alex –

8

Hãy thử với điều này:

#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

Cảm ơn bạn đã trả lời Cesar, nhưng điều này không trả lời được câu hỏi. Ví dụ của bạn chỉ chấp nhận các kết nối, trong khi những gì tôi yêu cầu là chọn hoặc (e) thăm dò ý kiến ​​hoặc xử lý sự kiện trên các kết nối được chấp nhận cho dữ liệu đến, xảy ra lỗi, v.v. –

+0

Ví dụ hoàn tất với kết nối, thời gian chờ, lỗi mạng, v.v. .. –

+0

Một lần nữa, cảm ơn bạn rất nhiều :) –