【发布时间】:2012-10-01 19:39:23
【问题描述】:
我有一个相当令人困惑的问题。
我正在使用一个大型 C++ 库在 Windows XP/7 上通过 UDP 处理一些专有协议。它在程序运行的整个过程中侦听一个端口,并等待来自远方的连接。
大多数时候,这很有效。但是,由于我遇到的一些问题,我决定在调用 WSARecvFrom 之后直接添加一个简单的调试打印(库中用于从我感兴趣的套接字接收数据报的 win32 函数,并告诉什么 IP和他们来自的港口)。
奇怪的是,在某些情况下,我发现数据包在 OS 级别 被丢弃(即我在 Wireshark 中看到它们,它们具有正确的 dst 端口,所有校验和都是正确的 - 但它们从未出现在我植入代码的调试打印中)。
现在,我完全相信“UDP 不能保证传送”这一事实(人们往往提到的有点过于频繁)——但这并不相关,因为数据包已收到通过机器 - 我在 Wireshark 中看到它们。
另外,我熟悉操作系统缓冲区和被填满的可能性,但奇怪的部分来了……
我进行了一些研究,试图找出哪些数据包被准确丢弃。我发现,所有丢弃的数据包都有两个共同点(虽然一些,但绝对不是大多数,不是 也放弃分享这些):
- 它们很小。协议中的许多数据包都很大,接近 MTU - 但所有丢弃的数据包都小于 100 字节(总)。
- 它们总是以下两种之一:一个 SYN 等效项(即对等方发送给我们以启动通信的第一个数据包)或 FIN 等效项(即对等方不再对通话感兴趣时发送的数据包)给我们)。
这两种品质中的任何一种都会影响操作系统缓冲区,并导致数据包被随机(甚至更有趣 - 有选择地)丢弃吗?
任何关于这个奇怪问题的线索将不胜感激。
非常感谢。
编辑(24/10/12):
我想我可能错过了一个重要的细节。似乎在到达之前丢弃的数据包有其他共同点:它们(我开始相信,只有它们)由“新”对等方发送到服务器,即它 之前没有尝试过联系。
例如,如果一个同步等效数据包从我们以前从未见过的对等点*到达,WSARecvFrom 将看不到它。然而,如果我们向我们自己的那个对等方发送了一个syn等效数据包(即使它当时没有回复),现在它向我们发送一个syn-等价的,我们会看到的。
(*) 我不确定这是一个我们没见过的peer(即ip:port)还是只是一个我们没见过的port之前。
这有帮助吗?
这是我从未听说过的某种 WinSock 选项吗? (如上所述,代码不是我的,所以它可能使用了我不知道的套接字选项)
再次感谢!
【问题讨论】:
-
我认为它没有因为
RecvFrom()from参数或套接字绑定而被删除? -
@Deanna:我坚信这是真的 - AFAIK
from问题应该使用 WSAGetLastError 引发一些错误代码(我得到的唯一一个是 WSAEWOULDBLOCK,AFAIK 意味着缓冲区中没有任何内容)片刻);套接字绑定应该没问题 - 接收和处理丢弃的一个(到同一端口)之前和之后的数据包。 -
同一个IP?您是否从问题 IP 中得到任何信息?
-
@Deanna:是的,有时它是同一个 IP。例如,有一次我在大约 5 秒的时间内看到来自同一 IP 的 5 个几乎相同的同步等效数据包,都没有到达
WSARecvFrom,但半秒后,我的代码启动了与该 IP 的连接(是的,它也可以启动)成功,并且它对我的seq-equivalent的回复被成功接收和处理。
标签: windows winapi sockets operating-system