首页 > 解决方案 > 如何确定 Windows 中 UDP 有效负载的大小?

问题描述

我试图弄清楚如何解决 Windows 中的问题。我使用的是 C# (net5.0),但如果您知道 C 或 C++ 中的答案,那应该不是真正的问题,因为我可以毫无问题地调用 DLL 中的函数。

在 Windows 10 上使用多播测试 UDP 处理时,我发现了一个问题:当我的缓冲区对于传入的有效负载来说太短时,System.Net.Sockets.Socket.ReceiveMessageFrom将缓冲区填充到其最大容量,不设置SocketOptions.FragmentedorSocketOptions.Multicast标志(并在调用之前设置made 导致“不支持”异常),并且该IPPacketInformation.Address字段为空。 ReceiveMessageFrom的返回值是我的缓冲区的大小,而不是数据包的大小。SocketOptions.Peek无论我做什么,我似乎都无法获得必要的分配大小(即使使用)。

当我的缓冲区足够长以容纳传入的有效负载时,(System.Net.Sockets.Socket)s.ReceiveMessageFrom填充缓冲区,设置SocketOptions.Multicast并将IPPacketInformation.Address字段设置为它接收到的多播组 IP。在这种情况下,返回值是实际接收到的数据量,当我的缓冲区大于接收到的数据时。

在Linux上,我可以设置SocketOptions.Fragmented并且它会正常工作:太小的缓冲区被填充,但返回值ReceiveMessageFrom设置为传入数据的实际大小。结合SocketOptions.Peek,这允许我分配一个足够大的新缓冲区来容纳它,并检索完整数据。(这非常类似于使用长度为 0 的缓冲区调用例如 Windows 注册表函数,并被告知您实际需要多大的缓冲区。)

Linux 方法的替代方法是尝试分配一个与接口允许的一样大的缓冲区,但System.Net.NetworkInformation.IPInterfaceProperties没有.Mtu成员,而System.Net.NetworkInformation.IPv6InterfaceProperties有。我不知道如何获得帧的最大大小,这是必要的,因为某些驱动程序支持称为“巨型帧”的功能,该功能可以超过 64kb。)

惠特:我的多播发送程序发送 26 字节长的数据包,其中包含从 A 到 Z 的整个美国大写字母。

我的多播接收程序是我一直在进行更改的地方。当我将该程序中的接收缓冲区设置为小于 26 字节时,我得到了有问题的行为。当我将其设置为 26 字节或更长时,我得到了正确的行为。

这个问题与操作系统级别或 Winsock 级别的缓冲区无关。如果需要,我将分别调整它们。我特别想确保我检索的数据ReceiveMessageFrom不会被截断。(当操作系统级别没有足够的缓冲区空间来排队数据时,它只会丢弃整个数据包。它不会将部分数据包写入队列。我的应用程序正在从调用接收部分数据ReceiveMessageFrom,它是并不表示有任何内容被截断。我需要弄清楚如何解决这个问题。)

我不能通过在为数据本身保留的区域中编码数据的大小来丢失数据包空间,因为这至少需要 2 个字节,而且我已经需要在这里挤很多。UDP 标头已经有一个 Length 字段,该字段包含我需要的内容,但我无权访问它。

谢谢你的帮助!

标签: c#windowssocketsudpmulticast

解决方案


推荐阅读