c# - 如何确定 Windows 中 UDP 有效负载的大小?
问题描述
我试图弄清楚如何解决 Windows 中的问题。我使用的是 C# (net5.0),但如果您知道 C 或 C++ 中的答案,那应该不是真正的问题,因为我可以毫无问题地调用 DLL 中的函数。
在 Windows 10 上使用多播测试 UDP 处理时,我发现了一个问题:当我的缓冲区对于传入的有效负载来说太短时,System.Net.Sockets.Socket.ReceiveMessageFrom
将缓冲区填充到其最大容量,不设置SocketOptions.Fragmented
orSocketOptions.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 字段,该字段包含我需要的内容,但我无权访问它。
谢谢你的帮助!
解决方案
推荐阅读
- nginx - 配置 nginx 以将 pgadmin 映射到 URI
- python - 无法使用 python 请求登录到 Indeed.com
- parsing - Bison 减少/减少冲突警告
- ios - 如何调试 Apple iOS 崩溃 - 仅限 App Store 下载
- android - 如何更改我的应用程序中“正在运行的应用程序”屏幕中显示的图标?
- git - 未找到模块,但在推送到 Heroku 时它在那里
- c++ - 堆栈/帧指针作为外部变量
- c# - 删除第一个和最后一个特定字符
- android - 如何在 Eclipse 中使用 Gradle 和 ADT?
- android - 是否可以在 webview 中运行硒测试?