【问题标题】:recv() has no time to receive all the UDP packets from a socket on Win 7?recv() 没有时间从 Win 7 上的套接字接收所有 UDP 数据包?
【发布时间】:2011-11-10 12:37:42
【问题描述】:

我正在为 Windows XP 和 Seven 开发一个网络应用程序。应用程序通过 UDP 接收数据并使用阻塞套接字、select(不是 WSAPoll)和 recv 函数。

为了进行测试,我使用了两台安装了不同操作系统的相同笔记本电脑:Dell Latitude D630、Core 2 Duo 2.2GHz、4Gb RAM、Broadcom NetXtreme 57xx Gigabit Controller。我得到了以下结果:

Windows XP Professional 32bit:网络监控应用程序显示网络接口以平均 35 MBytes/s 的速度从 LAN 接收数据。应用程序从平均速度为 30 MBytes/s 的套接字接收数据并检测到 13% 的丢失。

Windows 7 Enterprise 32bit:网络监控应用程序显示网络接口以平均 35 MBytes/s 的速度从 LAN 接收数据。应用程序从平均速度为 10 MBytes/s 的套接字接收数据并检测到 65% 的丢失。

在 Windows 7 上应用程序似乎没有足够的时间从套接字接收所有数据包。但是为什么结果与 Win XP 不同?

【问题讨论】:

  • 不同的硬件驱动程序,MMCSS 限制 7 上的网络活动,其他。我会检查增加接收缓冲区是否会合理地降低两个系统中的丢失率。
  • 我的接收缓冲区在创建套接字后通过 setsockopt 设置为 64K。感谢您的回答。我会检查你的假设。
  • 是的,增加缓冲区大小使接收更稳定。结果不同的原因是 Windows 7 上的接收缓冲区大小应该比 Win XP 上的大。我已将大小增加到 256KBytes,接收速度为 35MBps,两者都损失了 3%。谢谢。

标签: windows sockets udp


【解决方案1】:

当我在处理类似问题时遇到此帖子时,我将为正在处理此问题或类似问题的任何人提供以下内容。我希望这可以节省其他人一些时间。

我还要感谢 @Roman R. 的上述评论和 @Rom098 跟进的评论,指出缓冲区大小的变化也帮助了他/她。

使用带有 UDP 的 Windows 套接字以低数据速率在多个终端之间进行数据通信的应用程序在 Windows XP 上运行良好,但随着迁移到 Windows 7,我们开始遇到网络消息被丢弃的问题。

该架构是客户端通过发送和接收一系列UDP消息与服务器终端进行对话,客户端保持自己的状态。客户端有一个线程,即客户端线程,它处理用户输入以及向服务器终端发送和接收消息。服务器终端有一个线程,服务器线程,它处理来自其他终端的请求消息以及它自己的客户端线程。简单的消息序列如下所示:

  • 客户端向服务器端发送请求消息
  • 服务器终端响应确认消息
  • 服务器端处理请求并向客户端发送响应消息
  • 客户端向服务器端发送确认

查看上面的 cmets,我们使用调试器检查,发现 Windows 7 的默认 WinSock 接收和发送缓冲区大小为 8K(8192 字节)。在 Internet 上查找,似乎 Windows XP 对网络流量的处理速度更高。

我们对处理通信的网络层进行了两项更改。

第一种是使用setsockopt()函数将接收和发送缓冲区的大小加倍,使用以下代码。

iOptLen = sizeof(INT);
error = getsockopt (iSocket, SOL_SOCKET, SO_RCVBUF, (PCHAR)(&iOpt), &iOptLen);
if (error < 0) {
    error = WSAGetLastError();
} else if (iOpt < 1024 * 16) {
    iOpt = 1024 * 16;
    error = setsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (const PCHAR)(&iOpt), sizeof(iOpt));
    if (error < 0) {
        error = WSAGetLastError();
    }
}
iOptLen = sizeof(INT);
error = getsockopt (iSocket, SOL_SOCKET, SO_SNDBUF, (PCHAR)(&iOpt), &iOptLen);
if (error < 0) {
    error = WSAGetLastError();
} else if (iOpt < 1024 * 16) {
    iOpt = 1024 * 16;
    error = setsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (const PCHAR)(&iOpt), sizeof(iOpt));
    if (error < 0) {
        error = WSAGetLastError();
    }
}

我们所做的第二个更改是,如果客户端线程正在等待确认并且响应消息来自服务器终端,则将响应消息作为确认和响应的组合进行处理。我们所做的是假设确认消息在某个时间点被丢弃。

通过这两个更改,延迟不再明显,尽管我们的测量表明有时从服务器终端到客户端的确认消息仍然被丢弃。

另见

Change default socket buffer size under Windows 使用 Windows 注册表更改将默认缓冲区大小从 8K 修改为其他值。

What is the size of a socket send buffer in Windows? 与 TCP 相关,但提供了有关 setsockopt() 的其他信息。

Winsock UDP packets being dropped? 讨论了一个类似的问题,其中提供了许多答案,提供了额外的信息。

来自 Innominate.com 的Application Note: Windows 2000/XP TCP Tuning for High Bandwidth Networks 提供了一些有趣的信息,尽管可能有点过时,因为我知道在 Windows 7 中网络层已被重写。

来自 codeproject.com 上的 Michael Pan 的Real time communications over UDP protocol 有很多关于使用 UDP 的技术问题的详细信息。

【讨论】:

    猜你喜欢
    • 2015-11-28
    • 2019-08-18
    • 1970-01-01
    • 2015-08-19
    • 2012-12-29
    • 2012-04-23
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多