TCP套接字超时或无数据读取

时间:2016-04-28 11:18:18

标签: c sockets

如何识别套接字是否已超时或没有其他数据?

我有这个:

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

检查是否设置了EWOULDBLOCKEAGAIN后,即使没有超时也会设置它们。我需要执行不同的操作,具体取决于连接时间是否成功或者我是否已成功阅读

2 个答案:

答案 0 :(得分:5)

有三种方法可以检查超时:

  1. 使用SO_RCVTIMEO(我假设你正在做,你真的应该展示那部分!)。然后,您将errno设置为EWOULDBLOCKEAGAIN。如果您在阻塞套接字上遇到此错误,则知道它已超时,否则该函数将不会返回特定的错误集。对于非阻塞套接字,这种方法毫无意义。

    另请注意,此选项的setsockopt()参数在不同平台上有所不同。在POSIX平台上,参数是指向struct timeval的指针,而在Windows上,它是指向DWORD的指针。另请注意,在Windows上,recv函数实际在超时时返回 WSAETIMEDOUT

    如果套接字使用SO_RCVTIMEO超时,则它处于不确定状态,不应再使用。关闭它并重新连接。

  2. 使用SO_KEEPALIVE。没有标准或平台无关的设置超时的方法,默认为两个小时。 recv调用失败,errno设置为ETIMEDOUT

  3. 将保持活动信号添加到您的协议中。

  4. 使用方法一,在POSIX平台(如Linux或OSX)上,检查类似这样的内容

    l = recv(...)
    if (l < 0)
    {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
        {
            // Timeout, handle it somehow
        }
    
        break;  // Exit receiving loop
    }
    

    此处的重要部分是不检查errno,除非您实际知道有错误。如果recv返回非负值,则errno的值不确定。

    您还需要检查 EWOULDBLOCKEAGAIN,因为未指定将设置哪些

答案 1 :(得分:0)

您必须检查是否已设置ETIMEDOUT。 来自man page of recv(3):

  

ETIMEDOUT   连接建立期间连接超时,或者由于活动连接上的传输超时而导致连接超时。