【问题标题】:Inconsistent behavior transmitting bursts of UDP packets on Windows 7在 Windows 7 上传输 UDP 数据包突发的行为不一致
【发布时间】:2014-01-25 05:37:37
【问题描述】:

我有两个系统,都运行 Windows 7。源是 192.168.0.87,目标是 192.168.0.22,它们都连接到我桌子上的一个小开关。

源正在使用此程序向目标发送 100 个 UDP 数据包的突发 -

#include <iostream>
#include <vector>

using namespace std;

#include <winsock2.h>


int main()
{
    // It's windows, we need this.
    WSAData wsaData;
    int wres = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (wres != 0) { exit(1); }

    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s < 0) { exit(1); }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(0);

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { exit(3); }

    int max = 100;

    // build all the packets to send
    typedef vector<unsigned char> ByteArray;
    vector<ByteArray> v;
    v.reserve(max);
    for(int i=0;i<max;i++) {
        ByteArray bytes(150+(i%25), 'a'+(i%26));
        v.push_back(bytes);
    }

    // send all the packets out, one right after the other.
    addr.sin_addr.s_addr = htonl(0xC0A80016);// 192.168.0.22
    addr.sin_port = htons(24105);

    for(int i=0;i<max;++i) {
        if (sendto(s, (const char *)v[i].data(), v[i].size(), 0,
                   (struct sockaddr *)&addr, sizeof(addr)) < 0) {
            cout << "i: " << i << " error: " << errno;
        }
    }

    closesocket(s);

    cout << "Complete!" << endl;
}

现在,在第一次运行时,我会丢失大量 UDP 数据包(通常只有 1 个会通过!)。 在随后的运行中,所有 100 人都通过了。 如果我等待 2 分钟左右,然后再次运行,我又会丢失大部分数据包。

目标系统上的接收是使用 Wireshark 完成的。 我还在源系统上同时运行了 Wireshark,并且在所有情况下都找到了与目标完全相同的跟踪。

这意味着数据包在源机器上丢失,而不是在交换机或线路上丢失。

我还尝试运行 sysinternals 进程监视器,发现确实,所有 100 个 sendto 调用都会导致适当的 winsock 调用,但不一定是在线数据包中。

据我所知(使用 arp -a),在所有情况下,目标的 IP 都在源的 arp 缓存中。

谁能告诉我为什么 Windows 在处理这些数据包方面如此不一致?我在实际的应用程序中得到了这一点,我只需要稍微限制我的发送速率,但我想了解为什么它有时会起作用,而其他情况则不起作用。

哦,是的,我还尝试将系统交换为发送和接收,但行为没有改变。

【问题讨论】:

  • 我遇到过类似的情况。在我的情况下,一个似乎在 Windows XP 上运行良好的应用程序在 Windows 7 上出现问题,因为丢弃的 UDP 数据包/消息。我看到的是客户端向接收它的服务器发送请求消息,并在发送实际响应之前发送请求的确认。客户端永远不会看到确认,但它确实会看到随后的服务器响应消息。您的调查结果如何?
  • @RichardChambers - 我从来不知道到底发生了什么。我最终对源系统进行了轻微的速率限制,这适用于我的应用程序。
  • 我刚刚发现recv has no time to receive all the udp packets from a socket on win 7 有一个关于在Windows 7 下使用setsockopt() 函数来增加网络缓冲区大小的评论。我今天将尝试一下,看看会发生什么。跨度>

标签: windows-7 network-programming udp


【解决方案1】:

很可能客户端超出了 udp 发送缓冲区。可能在运行 ARP 协议以获取目标 MAC 地址时。你说你在第一次运行时丢失了数据报,如果你等待 2 分钟或更长时间。你为什么不向 Wireshark 检查第一次运行时会发生什么? (如果发送/接收 ARP 帧)

如果这是问题所在,您可以应用以下两种替代方法之一:

1-在运行之前确保 ARP 条目存在。

2-发送第一个数据报,等待1秒或更短,发送突发

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多