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

lll*_*ook -1 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;
}
Run Code Online (Sandbox Code Playgroud)

之后我检查EWOULDBLOCKEAGAIN设置,但即使超时没有发生,他们被设置.我需要执行不同的操作,具体取决于连接时间是否成功或者我是否已成功阅读

Som*_*ude 5

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

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

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

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

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

  3. 将keep-alive信令添加到您的协议中.


使用方法一,在POSIX平台(如Linux或OSX)上,您可以检查这样的内容

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

    break;  // Exit receiving loop
}
Run Code Online (Sandbox Code Playgroud)

这里的重要部分是不检查,errno除非你确实知道有错误.如果recv返回非负值,那么值errno是不确定的.

您还需要检查两者 EWOULDBLOCK,EAGAIN因为没有指定它们中的哪一个将被设置.