面临 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起

Posted

技术标签:

【中文标题】面临 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起【英文标题】:Facing an issue with recv() and send() winsock api. Recv() hangs while receving the last packet 【发布时间】:2009-08-22 15:57:54 【问题描述】:

我遇到了 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起。

问题描述:-

系统 A 的应用正在通过非阻塞套接字写入数据,而系统 B 的应用正在通过阻塞套接字接收 64k 块的数据。

似乎在读取可能小于或等于 64k 的最后一个 64k 数据包时,接收冻结。我不确定最后一个数据包的接收或最后一个数据包的发送是否存在问题,但我在我们的旧应用程序中间歇性地观察到此问题。

以前有没有人遇到过类似的问题?如果是,那么请提供您的意见。

如果没有,那么您能否提供一些故障排除技术来缩小根本原因。

仅供参考,我有 win2k3 服务器。

谢谢, 瓦伦

【问题讨论】:

您是通过 TCP 还是其他方式接收?你提到了数据包——这是 TCP 没有的概念——你不能接收 TCP 数据包——它只是一个流。 【参考方案1】:

Wireshark 是解决网络代码故障的好工具。它会以近乎实时的方式准确地向您显示哪些数据包正在进入和离开您的网络接口。

关于您的具体问题:您是说最后一块数据可能短于 64k 吗?如果是这样,您的协议应该包含一些消息长度信息,以便接收者 知道要查找多少数据。

【讨论】:

【参考方案2】:

几个猜测...

如果您使用的是 UDP,则可能会在途中丢弃一个或多个数据包(允许 UDP 随时这样做)。在这种情况下,您的接收器可能最终会等待根本不会到达的数据;要解决这个问题,您需要实现某种方式自动重新发送丢失的数据,或者(如果您并不严格需要所有数据),某种方式让发送方通知接收方他已完成传输,因此接收方还不如停止等待。 (当然,您还需要处理此通知被丢弃的情况……如果您想要 100% 的稳健性,它可能会变得复杂)

如果您使用 TCP,也许您没有仔细检查发送端的 send() 返回的值?如果您假设 send() 将始终发送您要求的字节数,那么您最终可能会认为 send() 发送了所有字节,而实际上它只发送了一些(或不发送)......所以发送方会认为传输已完成,而接收方会卡在等待不会到达的数据。

【讨论】:

【参考方案3】:

服务器发送数据的速度比接收器读取数据的速度快,您可能会遇到问题。您可以尝试增加接收缓冲区:

int nSocketBuffer = 131072; // 128k
if (setsockopt(m_sSocket,SOL_SOCKET,SO_RCVBUF,(LPCSTR)&nSocketBuffer,sizeof(int)) == SOCKET_ERROR)

    // socket error
    return false;

【讨论】:

以上是关于面临 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起的主要内容,如果未能解决你的问题,请参考以下文章

read() 和 recv() 以及 send() 和 write() 之间有啥区别?

Recv-Q+Send-Q>写入字节

Socket send函数和recv函数详解

read VS recv?关于 send 和 recv 的第四个参数 flag

read VS recv?关于 send 和 recv 的第四个参数 flag

Recv-Q 和 Send-Q 的使用