如何识别套接字是否已超时或没有其他数据?
我有这个:
setsockopt(cli_socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval)); //5 sec timeout
while(1)
{
l = recv(socket, ...);
if(l < 0)
break;
}
检查是否设置了EWOULDBLOCK
或EAGAIN
后,即使没有超时也会设置它们。我需要执行不同的操作,具体取决于连接时间是否成功或者我是否已成功阅读
答案 0 :(得分:5)
有三种方法可以检查超时:
使用SO_RCVTIMEO
(我假设你正在做,你真的应该展示那部分!)。然后,您将errno
设置为EWOULDBLOCK
或EAGAIN
。如果您在阻塞套接字上遇到此错误,则知道它已超时,否则该函数将不会返回特定的错误集。对于非阻塞套接字,这种方法毫无意义。
另请注意,此选项的setsockopt()
参数在不同平台上有所不同。在POSIX平台上,参数是指向struct timeval
的指针,而在Windows上,它是指向DWORD
的指针。另请注意,在Windows上,recv
函数实际在超时时返回 WSAETIMEDOUT
。
如果套接字使用SO_RCVTIMEO
超时,则它处于不确定状态,不应再使用。关闭它并重新连接。
使用SO_KEEPALIVE
。没有标准或平台无关的设置超时的方法,默认为两个小时。 recv
调用失败,errno
设置为ETIMEDOUT
。
将保持活动信号添加到您的协议中。
使用方法一,在POSIX平台(如Linux或OSX)上,检查类似这样的内容
l = recv(...)
if (l < 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
{
// Timeout, handle it somehow
}
break; // Exit receiving loop
}
此处的重要部分是不检查errno
,除非您实际知道有错误。如果recv
返回非负值,则errno
的值不确定。
您还需要检查 EWOULDBLOCK
和EAGAIN
,因为未指定将设置哪些。
答案 1 :(得分:0)
您必须检查是否已设置ETIMEDOUT。 来自man page of recv(3):
ETIMEDOUT 连接建立期间连接超时,或者由于活动连接上的传输超时而导致连接超时。