在 Poco Framework 中在一个线程中处理 websocket

Process websocket in one thread in Poco Framework

我正在尝试结合使用 Poco::Net::Websocket 和 Poco::Net::SocketReactor。 使用 Poco::Net;

class WSConnection: public HTTPRequestHandler{
    public:
    WSConnection(SocketReactor& reactor):_reactor(reactor){};
    void handleRequest(HTTPServerRequest& rqst, HTTPServerResponse& rpns){
       this->_ws = new Websocket(rqst, rspns);
       this->_reactor.addHandler(this._ws, this._onread_hnd);
       this->_reactor.addHandler(this._ws, this._onwrite_hnd);
       this->_reactor.addHandler(this._ws, this._onerror_hnd);
    }
    private:
       SocketReactor& _reactor;

};

class WSFactory : public HTTPRequestHandlerFactory{
    public:
    WSFactory(SocketRactor& reactor): _reactor(reactor){};
    void HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
{
       if (!IsWSRequest(request)){
           return 0;
       }
       return new WSConnection(this->_reactor);
    }
    private:
       bool IsWSRequest(const HTTPServerRequest& request){...}
       SocketReactor& _reactor;
}

int WSServerApp::main(...){
    Poco::Net::SocketReactor r;
    Poco::Thread thrd;
    WSFactory fctry(r);
    Poco::Net::HTTPServer serv(fctry, 35035);
    serv.start();
    thrd.start(r);
    waitForTerminationRequest();
    r.stop();
    thrd.join();
    serv.stop();
}

但是如果我的代码离开 handleRequest(),我会调用析构函数 WSConnection(); 还有其他方法可以在一个线程中处理连接吗?

我找到了解决方案。需要写两个类:

Server(ServerSocket 上的包装器)用部分副本重写 运行 方法 Poco::Net::TCPServer:: 运行().

Server::Server(const Poco::UInt16 port, const std::string& serv_name):
   Runnable(),
   SERVER_NAME(serv_name),
   _stop(true),
   _sock(port),
   _clients(),
   _thrd(),
   _param(new HTTPServerParams())
{
    _thrd.setPriority(Poco::Thread::PRIO_HIGH);
    _thrd.setName(SERVER_NAME);
    _param->setSoftwareVersion(SERVER_NAME);
}

void Server::run(){

    while(!_stop.load()){
        Poco::Timespan tm(250000);
        if (_sock.poll(tm, Socket::SELECT_READ)){
           auto ss = _sock.acceptConnection();
           ss.setNoDelay(true);
           #if defined(POCO_OS_FAMILY_UNIX)
           if (ss.address().family() == AddressFamily::UNIX_LOCAL)
           {
               //ONLY WEBSOCK
               throw Poco::IllegalStateException();
           }
           #endif
           auto conn = std::make_shared<Connection>(ss, _param);
          _clients.push_back(conn);  //std::vector<std::shared_ptr<Websocket>>
       }
   }

}

and Connection with partial copy Poco::Net::HTTPServerConnection::运行()

Connection::Connection(StreamSocket& ss, HTTPServerParams::Ptr param):
    HTTPServerSession(ss, param),
    _ws(),   //std::unique_ptr<Websocket>
    _rqst(), //std::unique_ptr<HTTPServerRequestImpl>
    _rspns() //std::unique_ptr<HTTPServerResponseImpl>
 {
     _rspns.reset(new HTTPServerResponseImpl(*this));
     _rqst.reset(new HTTPServerRequestImpl(*_rspns, *this, param));
    //may bee need try and cath with send error state
    Init(param);
    _ws.reset(new WebSocket(*_rqst, *_rspns));

 }


void Connection::Init(const HTTPServerParams::Ptr&  param){
    _rspns->setDate(Poco::Timestamp());
    _rspns->setVersion(_rqst->getVersion());
    _rspns->set("Server", param->getSoftwareVersion());
    _rspns->setKeepAlive(param->getKeepAlive() && _rqst->getKeepAlive());
}

并添加 SocketReactor 或 Socket::select 调用另一个线程。