在Poco框架中用一个线程处理websocket

Process websocket in one thread in Poco Framework

本文关键字:一个 线程 处理 websocket 框架 Poco      更新时间:2023-10-16

我尝试组合Poco::Net::Websocket和Poco::Net::SocketReactor。使用少::净;

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

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

我找到解决办法了。需要写两个类:

Server(ServerSocket上的包装器)重写运行方法,部分复制Poco::Net::TCPServer::run()

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

连接与部分复制Poco::Net::HTTPServerConnection::run()

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调用到另一个线程

相关文章: