UDP数据包,由Wireshark看到,被(甚至没有到达)WSARecvFrom丢弃 [英] UDP Packets, Seen by Wireshark, Dropped by (do not even reach) WSARecvFrom

查看:506
本文介绍了UDP数据包,由Wireshark看到,被(甚至没有到达)WSARecvFrom丢弃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个令人困惑的问题.
我正在使用一个大型C ++库在Windows XP/7上通过UDP处理某些专有协议.在整个程序运行期间,它在一个端口上侦听,并等待来自远程对等方的连接.

I have quite a bewildering problem.
I'm using a big C++ library for handling some proprietary protocol over UDP on Windows XP/7. It listens on one port throughout the run of the program, and waits for connections from distant peers.

在大多数情况下,这效果很好.但是,由于我遇到的一些问题,我决定在调用WSARecvFrom之后直接添加一个简单的调试打印(库中使用的win32函数从我感兴趣的套接字中接收数据报,并告诉该IP和它们来自的端口).
奇怪的是,在某些情况下,我发现数据包在 OS级别被丢弃(即,我在Wireshark中看到它们,它们具有正确的dst端口,所有校验和都是正确的-但它们从未出现过)在我已植入代码中的调试打印文件中.

Most of the time, this works well. However, due to some problems I'd experienced, I've decided to add a simple debug print directly after the call to WSARecvFrom (the win32 function used in the library to recv datagrams from my socket of interest, and tell what IP and port they came from).
Strangely enough, in some cases, I've discovered packets are dropped at the OS level (i.e. I see them in Wireshark, they have the right dst-port, all checksums are correct - but they never appear in the debug prints I've implanted into the code).

现在,我完全相信"UDP无法保证传送"这一事实(人们常常会提一提)-但这并不重要,因为已收到 数据包在机器上-我在Wireshark中看到了它们.
另外,我熟悉OS缓冲区和填充缓冲区的潜力,但是这里出现了一个奇怪的部分...

Now, I'm fully of the fact (people tend to mention a bit too often) that "UDP doesn't guarantee delivery" - but this is not relevant, as the packets are received by the machine - I see them in Wireshark.
Also, I'm familiar with OS buffers and the potential to fill up, but here comes the weird part...

我已经进行了一些研究,试图找出确切丢弃了哪些数据包.我发现,所有丢弃的数据包共有两个共同点(尽管有些,但绝对不是 most ,而没有 /em>也删除了分享这些内容):

I've done some research trying to find out which packets are dropped exactly. What I've discovered, is that all dropped packets share two things in common (though some, but definitely not most, of the packets that aren't dropped share these as well):

  1. 它们很小.协议中的许多数据包很大,接近MTU-但是所有丢弃的数据包都小于100字节(总值).
  2. 它们始终是以下两者之一:等同于SYN(即,对等方发送给我们以发起通信的第一个数据包)或等同于FIN(即对等方在不再对通话感兴趣时发送的数据包)给我们).

这两种质量中的任何一种都会影响OS缓冲区,并导致数据包被随机丢弃(或更有趣的是-有选择地)吗?
我们将不胜感激在这个奇怪问题上提出的任何看法.

Can either one of these two qualities affect the OS buffers, and cause packets to be randomly (or even more interesting - selectively) dropped?
Any light shed on this strange issue would be very appreciated.

非常感谢.

修改(12/10/24):

我想我可能错过了一个重要的细节.似乎到达之前丢弃的数据包还有其他共同点:它们(而且我开始相信,它们)是由新"对等方发送到服务器的,即,对等方以前没有尝试联系.

I think I may have missed an important detail. It seems that the packets dropped before arrival share something else in common: They (and I'm starting to believe, only they) are sent to the server by "new" peers, i.e. peers that it hasn't tried to contact before.

例如,如果同等的数据包来自我们从未见过的对等方*,则WSARecvFrom不会看到它.但是,如果我们已经向同伴我们自己发送了一个同等的数据包(即使当时没有答复),现在它又向我们发送了一个等价,我们会看到的.

For example, if a syn-equivalent packet arrives from a peer* we've never seen before, it will not be seen by WSARecvFrom. However, if we have sent a syn-equivalent packet to that peer ourselves (even if it didn't reply at the time), and now it sends us a syn-equivalent, we will see it.

(*)我不确定这是我们没有看到的 peer 还是仅仅是我们没有看到的 port 以前.

(*) I'm not sure whether this is a peer we haven't seen (i.e. ip:port) or just a port we haven't seen before.

这有帮助吗?
这是我从未听说过的WinSock选项吗? (如上所述,该代码不是我的,因此可能使用了我不知道的套接字选项)

Does this help?
Is this some kind of WinSock option I've never heard of? (as I stated above, the code is not mine, so it may be using socket options I'm not aware of)

再次感谢!

推荐答案

操作系统具有固定大小的缓冲区,用于缓冲已到达您的套接字但尚未被您读取的数据.当该缓冲区耗尽时,它将开始丢弃数据.调试日志记录可能会通过延迟您从套接字提取数据的速率来加剧这种情况,从而增加溢出的机会.

The OS has a fixed size buffer for data that has arrived at your socket but hasn't yet been read by you. When this buffer is exhausted, it'll start to discard data. Debug logging may exacerbate this by delaying the rate you pull data from the socket at, increasing the chances of overflows.

如果这是问题所在,您至少可以通过请求更大的recv缓冲区来减少它的实例.

If this is the problem, you could at least reduce the instances of it by requesting a larger recv buffer.

您可以使用以下方法检查套接字的recv缓冲区的大小

You can check the size of your socket's recv buffer using

int recvBufSize;
int err = getsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (char*)&recvBufSize, sizeof(recvBufSize));

,您可以使用设置更大的尺寸

and you can set it to a larger size using

int recvBufSize = /* usage specific size */;
int err = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (const char*)&recvBufSize, sizeof(recvBufSize));

如果仍然看到操作系统正在接收但没有传递给套接字客户端的数据,则可以考虑使用其他日志记录方法.例如

If you still see data being received by the OS but not delivered to your socket client, you could think about different approaches to logging. e.g.

  • 登录到RAM缓冲区并仅偶尔打印一次(以您配置为最有效的任意大小)
  • 来自低优先级线程的日志,要么接受对此的内存需求是不可预测的,要么添加代码以在日志满时从日志缓冲区中丢弃数据

这篇关于UDP数据包,由Wireshark看到,被(甚至没有到达)WSARecvFrom丢弃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆