recv()返回0

问题描述 投票:6回答:3

我有一个非常烦人的问题,我在其他论坛上发现了几次,但找不到合适的解决方案。问题是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或关机功能 导致在控制通道上发出RELEASE信号。到期 对于ATM使用单独的信号和数据通道的情况, RELEASE信号可能在最后一个 数据到达其目的地,导致该数据丢失。一 可能的解决方案是在最后一个之间编程足够的延迟 发送的数据以及closesocket或关闭功能需要ATM 套接字。

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

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

sockets shutdown zero recv closesocket
3个回答
12
投票

recv()仅在您请求一个0字节的缓冲区或另一个对等方已正常断开连接时才返回0。如果您没有收到期望的所有数据,则说明开始时您没有正确读取数据。请使用您的实际代码更新您的问题。


0
投票

我的猜测是您并没有真正发送您认为正在发送的所有数据。签出:

The Ultimate SO_LINGER page


0
投票
  • 当另一侧关闭连接时,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”被“破坏了”。

© www.soinside.com 2019 - 2024. All rights reserved.