Poco c++;对等方重置Websocket服务器连接
我正在编写一种聊天服务器应用程序,其中从一个websocket客户端接收的消息被发送到所有其他websocket客户端。为此,我将连接的客户端保存在一个列表中。当客户端断开连接时,我需要将其从列表中删除(以便将来的“发送”不会失败) 但是,有时当客户端断开连接时,服务器只会收到一个异常“由对等方重置连接”,并且代码没有机会从客户端列表中删除。有没有一种方法可以保证“很好”地通知连接已重置 我的代码是:Poco c++;对等方重置Websocket服务器连接,websocket,poco-libraries,Websocket,Poco Libraries,我正在编写一种聊天服务器应用程序,其中从一个websocket客户端接收的消息被发送到所有其他websocket客户端。为此,我将连接的客户端保存在一个列表中。当客户端断开连接时,我需要将其从列表中删除(以便将来的“发送”不会失败) 但是,有时当客户端断开连接时,服务器只会收到一个异常“由对等方重置连接”,并且代码没有机会从客户端列表中删除。有没有一种方法可以保证“很好”地通知连接已重置 我的代码是: void WsRequestHandler::handleRequest(HTTPServer
void WsRequestHandler::handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
{
int n;
Poco::Timespan timeOut(5,0);
try
{
req.set("Connection","Upgrade"); // knock out any extra tokens firefox may send such as "keep-alive"
ws = new WebSocket(req, resp);
ws->setKeepAlive(false);
connectedSockets->push_back(this);
do
{
flags = 0;
if (!ws->poll(timeOut,Poco::Net::Socket::SELECT_READ || Poco::Net::Socket::SELECT_ERROR))
{
// cout << ".";
}
else
{
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
if (n > 0)
{
if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_BINARY)
{
// process and send out to all other clients
DoReceived(ws, buffer, n);
}
}
}
}
while ((flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
// client has closed, so remove from list
for (vector<WsRequestHandler *>::iterator it = connectedSockets->begin() ; it != connectedSockets->end(); ++it)
{
if (*it == this)
{
connectedSockets->erase(it);
logger->information("Connection closed %s", ws->peerAddress().toString());
break;
}
}
delete(ws);
ws = NULL;
}
catch (WebSocketException& exc)
{
//never gets called
}
}
void WsRequestHandler::handleRequest(HTTPServerRequest&req、HTTPServerResponse&resp)
{
int n;
Poco::Timespan超时(5,0);
尝试
{
req.set(“连接”、“升级”);//删除firefox可能发送的任何额外标记,如“保持活动”
ws=新的WebSocket(请求、响应);
ws->setKeepAlive(false);
连接的插座->推回(此);
做
{
flags=0;
如果(!ws->poll(超时,Poco::Net::Socket::SELECT_READ | | Poco::Net::Socket::SELECT_ERROR))
{
//cout receiveFrame(缓冲区、sizeof(缓冲区)、标志);
如果(n>0)
{
if((标志和WebSocket::FRAME\u OP\u位掩码)==WebSocket::FRAME\u OP\u二进制)
{
//处理并发送给所有其他客户
数据接收(ws,buffer,n);
}
}
}
}
while((flags&WebSocket::FRAME\u OP\u BITMASK)!=WebSocket::FRAME\u OP\u CLOSE);
//客户端已关闭,请从列表中删除
对于(向量::迭代器it=connectedSockets->begin();it!=connectedSockets->end();++it)
{
如果(*it==此)
{
已连接套接字->擦除(it);
日志程序->信息(“连接已关闭%s”,ws->peerAddress().toString());
打破
}
}
删除(ws);
ws=NULL;
}
捕获(WebSocketException和exc)
{
//从未接到过电话
}
}
我扩展了捕获,为“对等连接重置”做了一些异常处理
我扩展了catch,为“对等连接重置”做了一些异常处理 请参见receiveFrame(): 返回接收到的字节数。返回值0表示对等方已关闭或关闭连接 所以,如果receiveFrame()调用返回零,则可以执行相应的操作。请参阅receiveFrame(): 返回接收到的字节数。返回值0表示对等方已关闭或关闭连接
因此,如果receiveFrame()调用返回零,您可以采取相应的行动。我不知道这是否是问题的答案,但您所做的实现没有处理PING帧。目前(从我的POCO版本1.7.5开始),POCO框架并没有自动完成这项工作。我贴了一张照片。根据RFC(6465),乒乓和乒乓帧(除其他外)用作保持活动功能。因此,为了使您的连接随着时间的推移保持稳定,这可能是正确操作的关键。这大部分是我自己的猜测工作,因为我现在自己也在尝试
@Alex,我相信您是POCO的主要开发人员,如果您能对我的答案发表评论,我将不胜感激。我不知道这是否是问题的答案,但您所做的实现并不涉及PING帧。目前(从我的POCO版本1.7.5开始),POCO框架并没有自动完成这项工作。我贴了一张照片。根据RFC(6465),乒乓和乒乓帧(除其他外)用作保持活动功能。因此,为了使您的连接随着时间的推移保持稳定,这可能是正确操作的关键。这大部分是我自己的猜测工作,因为我现在自己也在尝试
@Alex,你是POCO的主要开发者,我相信,如果你能对我的答案发表评论,我将不胜感激。来这里参加聚会有点晚了。。。但我也在使用Poco和Websockets——正确处理断开连接是很棘手的 最后,我自己实现了一个简单的ping功能,客户端为接收到的每个WS-Frame发送一个ACK消息。服务器端的一个单独线程尝试读取ACK消息,现在它将通过查看标志| WebSocket::FRAME_OP_CLOSE来检测客户端何时断开连接
//Serverside - POCO. Start thread for receiving ACK packages. Needed in order to detect when websocket is closed!
thread t0([&]()->void{
while((!KillFlag && ws!= nullptr && flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE && machineConnection != nullptr){
try{
if(ws == nullptr){
return;
}
if(ws->available() > 0){
int len = ws->receiveFrame(buffer, sizeof(buffer), flags);
}
else{
Util::Sleep(10);
}
}
catch(Poco::Exception &pex){
flags = flags | WebSocket::FRAME_OP_CLOSE;
return;
}
catch(...){
//log::info(string("Unknown exception in ACK Thread drained"));
return;
}
}
log::debug("OperatorWebHandler::HttpRequestHandler() Websocket Acking thread DONE");
});
在客户端,每次从服务器(POCO)收到WS-frame时,我都会向服务器(JS)发送一个虚拟的“ACK”消息
来这里参加聚会有点晚了。。。但我也在使用Poco和Websockets——正确处理断开连接是很棘手的 最后,我自己实现了一个简单的ping功能,客户端为接收到的每个WS-Frame发送一个ACK消息。服务器端的一个单独线程尝试读取ACK消息,现在它将通过查看标志| WebSocket::FRAME_OP_CLOSE来检测客户端何时断开连接
//Serverside - POCO. Start thread for receiving ACK packages. Needed in order to detect when websocket is closed!
thread t0([&]()->void{
while((!KillFlag && ws!= nullptr && flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE && machineConnection != nullptr){
try{
if(ws == nullptr){
return;
}
if(ws->available() > 0){
int len = ws->receiveFrame(buffer, sizeof(buffer), flags);
}
else{
Util::Sleep(10);
}
}
catch(Poco::Exception &pex){
flags = flags | WebSocket::FRAME_OP_CLOSE;
return;
}
catch(...){
//log::info(string("Unknown exception in ACK Thread drained"));
return;
}
}
log::debug("OperatorWebHandler::HttpRequestHandler() Websocket Acking thread DONE");
});
在客户端,每次从服务器(POCO)收到WS-frame时,我都会向服务器(JS)发送一个虚拟的“ACK”消息
你有没有找到解决问题的办法?当客户端断开连接时,我也会得到“由对等方重置连接”。你有没有找到解决问题的方法?当客户端断开连接时,我还会收到“由对等方重置连接”的消息。报告了有关此问题的问题:报告了有关此问题的问题:
websocket.onmessage = (evt) => {
_this.receivedData = JSON.parse(evt.data);
websocket.send("ACK");
};