2010-04-30 21 views
2

目前我正在试图修复一个bug在我写有关套接字select()调用的代理服务器。我正在使用Poco C++库(使用SocketReactor),问题实际上是在Poco代码中,这可能是一个错误,但我还没有从它们那里收到任何确认。插槽选择()办理突然断开连接

正在发生的事情是只要连接突然终止插座select()调用时立即返回这是什么,我相信它的目的是做什么?无论如何,它会返回可读集文件描述符中的所有断开连接的套接字,但问题是当Poco尝试触发onReadable事件处理程序时会抛出异常“套接字未连接”,这是我将代码放到处理它。鉴于异常被无声捕获并且onReadable事件永远不会被触发,select()调用会立即返回,从而导致SocketReactor中的无限循环。

我正在考虑修改波苏代码,这样,而不是捕捉异常默默地它激发了一个名为onDisconnected或类似的东西,这样可以进行清理新事件。

我的问题是,是否有确定插座是否结束异常使用select()调用的任何优雅的方式?我正在考虑使用异常消息来确定何时发生这种情况,但这对我来说似乎很脏。

+1

您是否为ErrorNotification事件注册了处理程序? – nos 2010-04-30 07:14:44

+0

是的,没有错误事件被激发。 – Genesis 2010-04-30 07:32:24

+0

我对Poco一无所知,但总的来说,select()不报告可读套接字和断开连接套接字之间的区别。它报告一个套接字在关闭/丢失/终止时是可读的。随后在套接字上读取,然后指示是否发生断开连接,以及是否正常或异常。听起来Poco在读取套接字时发现了一个异常的断开连接(hense异常),而不是吞下它并返回到select(),它应该停止处理套接字。这明确暗示了Poco里面的一个bug。 – 2010-05-01 10:13:57

回答

1

看样子你是正确的雷米。我设法区分插座是否已经断开,使用下面的代码(这是加入到波科/网络/ src目录/ SocketImpl.cpp):

bool SocketImpl::isConnected() 
{ 
int bytestoread; 
int rc; 
fd_set fdRead; 

FD_ZERO(&fdRead); 
FD_SET(_sockfd, &fdRead); 

struct timeval tv; 
tv.tv_sec = 0; 
tv.tv_usec = 250000; 

rc = ::select(int(_sockfd) + 1, &fdRead, (fd_set*) 0, (fd_set*) 0, &tv); 
ioctl(FIONREAD, &bytestoread); 

return !((bytestoread == 0) && (rc == 1)); 
} 

从我的理解,这个检查插座是否可读使用电话select()然后检查该套接字上可用的实际字节数。如果套接字报告它是可读的但字节是0,那么套接字实际上并没有连接。

虽然这这里回答我的问题,因为我不能想出一个办法,在波苏SocketReactor代码来解决这个不幸的是这并没有解决我的问题波科。我试图创建一个名为DisconnectNotification的新事件,但不幸的是无法调用该事件,因为在关闭的套接字上出现ReadNotification时抛出的错误。

2

我有同样的问题。解决它的唯一方法是控制客户端应用程序退出代码。我使用的解决方案是在反应器在客户端终止之前发送关闭信号。然后在服务器上,您只需关闭套接字。

//Client: 
//Handler Class: onWrite 
Packet p = Packet::Shutdown(); 

if (p.fn == "shutdown") 
{ 
    _reactor.stop(); 
    delete this; 
} 

//Server 
//Accepter Class: onRead 
if (p.fn == "shutdown") 
{ 
    printf("%s has disconnected", _username.c_str()); 
    _socket.close(); 
    delete this; 
} 
1

正好赶上在OnReadable()ConnectionResetException(处理ReadableNotification) 然后它处理“连接被对方​​复位”正确。

catch(Poco::Net::ConnectionResetException &ex) 
{ 
    _socket.shutdownSend(); 
    delete this; 
}