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

recv()套接字函数返回长度为0的数据,c,sockets,tcp,C,Sockets,Tcp,我有一个应用程序,它在端口号5005上与另一个设备(带有web服务器的硬件设备)建立了套接字连接 现在,如果我的硬件设备断开连接,那么我将与该设备断开连接 这是否意味着我的插座 使用到现在为止都是无效的 我收到什么特别的信息吗 空字符或其他什么 这种脱节发生了 如果插座连接是我的 既然已经无效了,那为什么呢 不支持recv()套接字函数吗 抛出和套接字错误。相反 为什么我要接收0的数据 长度 感谢当recv返回值0时,表示连接已关闭 见 这些调用返回接收到的字节数,如果出现错误,则返回-1 发生

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

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

  • 这是否意味着我的插座 使用到现在为止都是无效的

  • 我收到什么特别的信息吗 空字符或其他什么 这种脱节发生了

  • 如果插座连接是我的 既然已经无效了,那为什么呢 不支持recv()套接字函数吗 抛出和套接字错误。相反 为什么我要接收0的数据 长度

  • 感谢当
    recv
    返回值0时,表示连接已关闭

    这些调用返回接收到的字节数,如果出现错误,则返回-1 发生。 当对等方已执行有序操作时,返回值将为0 关闭

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

    编辑

    现在,正如valdo在下面指出的那样,也有可能存在一个半封闭的TCP连接,在这个连接中,您无法再接收任何数据,但您可以继续向套接字写入数据,直到您完成数据发送。有关更多详细信息,请参阅本文:。不过,听起来你没有这种情况

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

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


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

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

    recv不会抛出,因为它是C函数


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

    假设您正在与web服务器通信,我假设您使用的是TCP套接字

    答复:

  • 插座不会因断开而失效;它们只是进入断开连接的状态。对它们调用套接字操作仍然是安全的

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

  • 这个问题没有真正的答案——这是socket API最初是如何实现的,我们一直在坚持这个实现,因为每个人都在实现Berkley socket


  • 我想您正在使用TCP与设备通信

  • 套接字本身仍然“有效”,但连接已丢失

  • 当另一台主机关闭连接时,
    recv()
    的返回值为0(此断开是否正常并不重要)

  • 套接字函数类似于
    C
    函数:它们不会抛出,因为它们可以在
    C
    程序中使用,在这些程序中不存在异常


  • 同意罗伯特·S·巴恩斯的观点。除了声称套接字现在“无效”之外


    它仍然有效。你可以用它。您甚至可以向对等方发送数据。你唯一不能用它做的就是调用
    recv

    来纠正现有答案中的大量错误陈述:

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

  • 当这种断开连接发生时,我是否会收到任何特殊消息,如空字符或其他信息
  • 否,您从
    recv()
    获得零返回值。这就是它的目的。它在带外传递,而不是在数据缓冲区中

  • 如果我使用的套接字连接无效,那么为什么
    recv()
    socket函数不抛出
  • 因为它是一个C API,在C中或Unix系统调用中都没有
    抛出

    和套接字错误

    因为这不是一个错误

    相反,我为什么接收长度为0的数据


    您没有“接收长度为0的数据”。您将收到一个返回值零而不是数据。

    如果您至少使用winsock2将套接字设置为非阻塞,那么当没有数据可接收时,您将得到0,无论套接字的另一端是否有应用程序,我也看到了另一端关闭套接字的情况。 recv返回0,WSAGetLastError()返回0,但/nothing/位于另一端。
    实际上,我来这里是想了解您是如何检测到另一端没有任何东西的。

    我熟悉的几乎所有应用程序都只使用阻止呼叫。只有当select()/epoll()告诉您套接字是可读的时,才能读取它。当它可读时,你读取它并接收0字节,那么你就知道要关闭它。

    所以我需要做的是,如果我得到一个返回值0,那么我需要关闭该套接字并打开另一个套接字,对吗?@ckv实际上还有一种可能性,
    recv()
    返回零。当要接收的字节大小为零时,它会执行此操作。我只是偶尔穿过这些耙子?