Windows Wireshark看到的UDP数据包被WSARecvFrom丢弃(甚至没有到达)
我有一个相当令人困惑的问题。Windows Wireshark看到的UDP数据包被WSARecvFrom丢弃(甚至没有到达),windows,winapi,sockets,operating-system,Windows,Winapi,Sockets,Operating System,我有一个相当令人困惑的问题。 我正在使用一个大的C++库来处理一些在Windows XP/7上的UDP专有协议。它在整个程序运行期间监听一个端口,并等待来自远程对等方的连接 大多数情况下,这很有效。然而,由于我遇到了一些问题,我决定在调用WSARecvFrom(库中使用的win32函数从我感兴趣的套接字中接收数据报,并告诉它们来自哪个IP和端口)之后直接添加一个简单的调试打印 奇怪的是,在某些情况下,我发现数据包是在操作系统级丢弃的(即,我在Wireshark中看到它们,它们有正确的dst端口,
我正在使用一个大的C++库来处理一些在Windows XP/7上的UDP专有协议。它在整个程序运行期间监听一个端口,并等待来自远程对等方的连接 大多数情况下,这很有效。然而,由于我遇到了一些问题,我决定在调用
WSARecvFrom
(库中使用的win32函数从我感兴趣的套接字中接收数据报,并告诉它们来自哪个IP和端口)之后直接添加一个简单的调试打印
奇怪的是,在某些情况下,我发现数据包是在操作系统级丢弃的(即,我在Wireshark中看到它们,它们有正确的dst端口,所有校验和都是正确的,但它们从未出现在我植入代码的调试打印中)
现在,我完全明白“UDP不能保证交付”这一事实(人们往往有点过于频繁地提及),但这并不重要,因为机器接收到的数据包,,我在Wireshark中看到了它们。另外,我对操作系统缓冲区和填充的可能性很熟悉,但奇怪的是 我做了一些研究,试图找出哪些数据包被丢弃了。我发现,所有丢弃的数据包都有两个共同点(尽管一些,但肯定不是大多数,没有丢弃的数据包也有这两个共同点):
任何关于这个奇怪问题的说明都将不胜感激 非常感谢
编辑(2012年10月24日): 我想我可能错过了一个重要的细节。在到达之前丢弃的数据包似乎有其他共同点:它们(我开始相信,只有它们)是由“新”对等方发送到服务器的,也就是说,以前从未尝试联系过的对等方 例如,如果一个syn等效数据包从一个我们以前从未见过的对等方*到达,
WSARecvFrom
将看不到它。但是,如果我们已经将一个syn等效数据包发送给该对等方我们自己(即使它当时没有回复),现在它将一个syn等效数据包发送给我们,我们将看到它
(*)我不确定这是一个我们从未见过的对等端口(即ip:port)还是一个我们从未见过的端口
这有用吗?这是我从未听说过的WinSock选项吗?(如上所述,代码不是我的,因此它可能使用我不知道的套接字选项)
再次感谢 操作系统有一个固定大小的缓冲区,用于存储已到达套接字但尚未被您读取的数据。当这个缓冲区耗尽时,它将开始丢弃数据。调试日志记录可能会延迟从套接字中提取数据的速率,从而增加溢出的可能性,从而加剧这种情况 如果这是问题所在,您至少可以通过请求更大的recv缓冲区来减少实例 您可以使用以下命令检查套接字recv缓冲区的大小:
int recvBufSize;
int err = getsockopt(socket, SOL_SOCKET, SO_RCVBUF,
(char*)&recvBufSize, sizeof(recvBufSize));
您可以使用
int recvBufSize = /* usage specific size */;
int err = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
(const char*)&recvBufSize, sizeof(recvBufSize));
如果您仍然看到操作系统正在接收数据,但没有发送到套接字客户端,那么您可以考虑使用不同的日志记录方法。e、 g
- 记录到RAM缓冲区,并仅偶尔打印(以您认为最有效的大小)
- 从低优先级线程记录日志,要么接受此线程的内存需求不可预测,要么添加代码以在日志缓冲区满时丢弃数据
在redhat linux上也遇到了同样的问题。 这是一个路由问题 区域协调安排如下:
ping-I
)我遇到了一个非常类似的问题,在确认接收缓冲区没有导致丢包后,我了解到这是因为我将接收超时设置为1ms太低。将套接字设置为非阻塞,而不设置接收超时为我解决了这个问题。感谢您的回答,但是它仍然没有阐明被丢弃的数据包的具体特征(短、类syn或类fin、仅数据包)。另外,我可能还不够清楚,但日志记录并没有导致问题,我添加它来调查问题。我不需要它,否则:)我不认为当套接字的recv缓冲区填充时,数据丢失有任何定义的行为。您是否尝试过增加缓冲区大小以查看是否会减少丢弃的数据包数?我将尝试查询和调整缓冲区大小,但我同意-
“我认为没有任何已定义的行为