我有两个系统,都运行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在如何处理这些数据包方面如此不一致?我在实际的应用程序中得到了这个,我只是对我的发送速率进行了一些限制,但我想了解为什么它有时会起作用而不是其他的。
哦,是的,我也尝试交换系统进行发送和接收,但行为没有变化。
答案 0 :(得分:0)
最有可能的是客户端超出了udp发送缓冲区。也许在ARP协议运行时获取目标MAC地址。你说你在第一次运行时会丢失数据报,如果你等待2分钟或更长时间。你为什么不和Wireshark一起检查第一次运行会发生什么? (如果发送/接收ARP帧)
如果这是问题,您可以应用以下两种选择之一:
1 - 运行前确保ARP条目存在。
2 - 发送第一个数据报,等待1秒或更短时间,发送突发