recv()套接字函数返回长度为0的数据

时间:2010-06-22 07:14:31

标签: c sockets tcp

我有一个应用程序,它在端口号5005上与另一个设备(带有Web服务器的硬件设备)建立了套接字连接。

现在,如果我的硬件设备断开连接,那么我将断开与设备的连接。

  1. 这是否意味着我是套接字 使用到现在变得无效。

  2. 我是否收到任何特殊消息 null字符或什么时候 这种脱节发生了。

  3. 如果我是套接字连接 已成为无效然后为什么 不是recv()套接字函数 throw和SOCKET_ERROR。代替 为什么我会收到0的数据 长度。
  4. 由于

8 个答案:

答案 0 :(得分:35)

recv返回值0表示连接已关闭时。

请参阅recv man page:

  

这些调用返回接收的字节数,如果发生错误则返回-1   发生了。   当对等体有序执行时,返回值将为0   关机。

在回答问题#1时,是的套接字现在无效。您必须创建新的套接字和连接以进行进一步的通信。

修改

现在正如valdo在下面指出的那样,也有可能有一个半封闭的TCP连接,你不能再接收它,但你可以继续写入套接字,直到你完成数据发送。有关详细信息,请参阅此文章:TCP Half-Close。听起来不像你有这种情况。

在回答问题#2时,基本上有两种方法可以检测闭合的套接字。这假设套接字经历了有序关闭,这意味着对等体称为shutdownclose

第一种方法是从套接字读取,在这种情况下,返回值为0.另一种方法是写入套接字,这将导致抛出SIG_PIPE信号,指示管道损坏。

为了避免信号,您可以设置MSG_NOSIGNAL套接字选项,在这种情况下send将返回-1并将errno设置为EPIPE

答案 1 :(得分:9)

同意Robert S. Barnes。除了声称套接字现在“无效”之外。

它仍然有效。你可以使用它。您甚至可以将数据发送给对等方。你唯一不能做的就是打电话recv

答案 2 :(得分:2)

如果recv返回0,则表示对等方已关闭套接字。

recv不会因为它的C函数而抛出。

如果有错误,recv将返回-1。在这种情况下,您的应用程序必须检查错误类型。请注意,返回-1并不意味着对等体已关闭其套接字。

答案 3 :(得分:2)

我想您正在使用TCP与您的设备进行通信。

  1. 套接字本身仍然“有效”,但连接丢失了。

  2. 当其他主机关闭连接时,recv()的返回值为0(这种断开连接是否正常无关紧要)

  3. 套接字函数与C函数类似:它们不会抛出,因为它们可以在C程序中使用,其中存在的异常。

答案 4 :(得分:1)

鉴于您正在与Web服务器通信,我假设您正在使用TCP套接字。

回答:

  1. 套接字因断开连接而无效;他们只是进入断开状态。在它们上调用套接字操作仍然是安全的。

  2. 发生断开连接时,您不会收到任何特殊消息。如果以阻塞方式调用recv(),它将在断开连接时返回,并且从调用返回的字节数将与您请求的字节数不匹配。

  3. 对此没有真正的答案 - 它是最初实现套接字API的方式,而我们仍然坚持使用每个实现Berkley套接字的实现。

答案 5 :(得分:0)

要纠正现有答案中的许多错误陈述:

  
      
  1. 这是否意味着我到目前为止使用的套接字无效。
  2.   

不。这意味着对等方已关闭连接,或将其关闭以从其末端输出。您的套接字仍然有效。您可以再次调用recv(),但是得到的只是另一个零。您也可以在其上调用send(),如果对等方仅关闭连接以进行输出,则将发送数据。

  
      
  1. 断开连接时,是否收到任何特殊消息,例如空字符或其他内容。
  2.   

否,您从recv()获得零返回值。那就是它的目的。它是带外传送的,而不是在数据缓冲区中传送的。

  
      
  1. 如果我的套接字连接无效,那么为什么recv()套接字函数不抛出
  2.   

因为它是C API,所以C或Unix系统调用中都没有throws

  

和SOCKET_ERROR。

因为这不是错误。

  

相反,为什么我会收到长度为0的数据。

您不会“接收长度为0的数据”。您收到的返回值为零,而不是数据。

答案 6 :(得分:-1)

我熟悉的几乎所有应用程序都仅使用阻止呼叫。仅当select()/ epoll()告诉您可读性时,您才读取套接字。当它可读时,您读取并接收了0个字节,便知道要关闭它。

答案 7 :(得分:-2)

如果将套接字设置为非阻塞(至少使用winsock2),则在没有数据要接收时,无论套接字的另一端是否有应用程序,您都将获得0。看到了另一端已关闭套接字的位置。 recv返回0,WSAGetLastError()返回0,但/ nothing /在另一端。 我实际上是来这里了解您如何发现另一端没有任何东西的。