我有一个相当令人困惑的问题。
我正在使用一个大型 C++ 库在 Windows XP/7 上通过 UDP 处理一些专有协议。它在程序运行的整个过程中侦听一个端口,并等待来自远距离对等点的连接。
大多数时候,这很好用。但是,由于我遇到的一些问题,我决定在调用之后直接添加一个简单的调试打印WSARecvFrom
(库中使用的 win32 函数,用于从我感兴趣的套接字接收数据报,并告诉它们的 IP 和端口来自)。
奇怪的是,在某些情况下,我发现数据包在操作系统级别被丢弃(即我在 Wireshark 中看到它们,它们具有正确的 dst 端口,所有校验和都是正确的 - 但它们从未出现在我的调试打印中植入代码中)。
现在,我完全相信“UDP 不能保证交付”这一事实(人们往往会经常提及)——但这不相关,因为数据包是由机器接收的——我在 Wireshark 中看到了它们。
此外,我熟悉操作系统缓冲区和填满的可能性,但奇怪的部分来了……
我做了一些研究,试图找出哪些数据包被丢弃了。我发现,所有丢弃的数据包都有两个共同点(虽然一些,但绝对不是大多数,没有丢弃的数据包也共享这些):
- 他们很小。协议中的许多数据包都很大,接近 MTU - 但所有丢弃的数据包都小于 100 字节(总)。
- 它们总是两个之一:一个 SYN 等效(即对等方发送给我们以启动通信的第一个数据包)或 FIN 等效性(即当对等方不再有兴趣与我们交谈时发送的数据包) .
这两种品质中的任何一种都会影响操作系统缓冲区,并导致数据包被随机(或更有趣 - 有选择地)丢弃吗?
任何关于这个奇怪问题的线索将不胜感激。
非常感谢。
编辑(24/10/12):
我想我可能错过了一个重要的细节。似乎在到达之前丢弃的数据包有其他共同点:它们(我开始相信,只有它们)是由“新”对等方发送到服务器的,即它之前没有尝试联系的对等方。
例如,如果一个同步等效数据包从我们以前从未见过的对等点*到达,则它不会被WSARecvFrom
. 但是,如果我们自己向该对等方发送了一个 syn-equivalent 数据包(即使它当时没有回复),现在它向我们发送了一个 syn-equivalent,我们将看到它。
(*) 我不确定这是一个我们没见过的对等点(即 ip:port)还是只是一个我们以前没见过的端口。
这有帮助吗?
这是我从未听说过的某种 WinSock 选项吗?(如上所述,代码不是我的,所以它可能使用了我不知道的套接字选项)
再次感谢!