recv()返回0

时间:2012-05-10 01:26:47

标签: sockets shutdown zero recv closesocket

我有一个非常讨厌的问题,我在其他论坛上发现了几次,但我找不到合适的解决方案。 问题是recv()在连接的最后几个字节返回0。以下是一些背景信息。

  • 两个(客户端/服务器)应用程序都在同一台计算机上运行。
  • 两个(客户端/服务器)套接字都是非阻塞的
  • 传输的数据大小为53个字节。
  • 执行最后一次send()/ recv()时,(客户端/服务器)都调用shutdown和closesocket。
  • 我也尝试过使用SO_LINGER 10秒,但没有成功

我多次调用send()(小块),从客户端调用53个字节。 服务器多次调用recv()(4字节请求)并读取49个字节然后返回0(54字节 - 49字节,因此缺少4个字节)。

MSDN和一些论坛为非阻塞套接字编写:

  • recv()肯定会返回<错误时为0,并且设置了errno / WSAGetLastError
  • recv()在对方关闭连接时肯定返回= 0
  • recv()肯定会返回>读取数据时为0

MSDN也说:

  

使用带有SD_SEND或SD_BOTH的closesocket或shutdown函数   导致RELEASE信号在控制信道上发送出去。应有   ATM可以使用单独的信号和数据通道   RELEASE信号可以在最后一个之前到达远程端   数据到达目的地,导致数据丢失。一   可能的解决方案是在最后一个之间编程足够的延迟   发送的数据和closesocket或shutdown函数调用ATM   插座。

这在recv()和send()的示例中被视为:http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx

但仍然没有成功,在收到49字节后,我仍然在10%的连接中得到一些中断,90%的连接成功。有任何想法吗? THX。

3 个答案:

答案 0 :(得分:11)

recv()仅在您请求0字节缓冲区或其他对等方已正常断开连接时返回0。如果您没有收到所需的所有数据,那么您开始时并没有正确读取数据。请使用您的实际代码更新您的问题。

答案 1 :(得分:0)

我的猜测是你并没有真正发送你认为发送的所有数据。退房:

The Ultimate SO_LINGER page

答案 2 :(得分:-1)

  • 当另一端关闭连接时,recv()绝对返回= 0

这不是完全正确的,在以下使用非阻塞winsock2 tcp的代码中,当没有可用数据时,select返回1,recv返回0,WSAGetLastError()也是如此。

fd_set test = {1, socket};
const timeval timeout = {0, 0};
if (!::select(0, &test, nullptr, nullptr, &timeout)) return 0;
int done = ::recv(socket, buffer, 1, 0);

即使另一端呼叫后,这种情况仍会继续:

::shutdown(socket, SD_BOTH);
::closesocket(socket);

,然后结束。通讯正常进行,只是:: recv似乎“中断”。