C#开发UDP抓包程序报“请求的地址在其上下文中无效”异常
使用C#编写程序捕获调制解调器发送的UDP数据时,运行代码抛出如下异常:
The requested address is not valid in its context at
System.Net.Sockets.Socket.setMulticastOption(SocketOptionName
optionName, MulticastOption MR) at
System.Net.Sockets.Socket.SetSocketOption(SocketOptionLevel
optionLevel, SocketOptionName optionName, Object optionValue) at
CAA..ctor() in C:\Users\Muhammed Kara\source\repos\UDPprogram\UDPprogram\CAA.cs:line 25
Wireshark抓包得到的报文属性:
- 源IP:192.168.1.150
- 目的IP:192.168.1.140
- 源端口:32768
- 目的端口:50000
抛出地址无效异常的核心原因有3个:
- 误用组播接收逻辑:抓包显示的目的IP192.168.1.140属于普通单播地址,不在224.0.0.0/4的组播地址段内,代码调用
SocketOptionName.AddMembership尝试将单播地址作为组播地址加入组播组,直接触发套接字选项配置错误。 - 端口配置不匹配:抓包显示报文目的端口为50000,代码中绑定的监听端口是9999,即使解决组播配置错误,也无法收到目标报文。
- 存在无效配置项:
SocketOptionName.NoDelay是TCP协议专属的禁用Nagle算法选项,UDP是无连接数据报协议,设置该选项无实际意义;组播TTL设置为0代表报文仅能在本机环回传输,无法接收外部设备发来的报文。
当前场景下要接收的是发往本机的单播UDP报文,完全不需要配置任何组播相关参数,按以下步骤修改即可:
- 将监听端口从9999修改为抓包得到的目的端口50000
- 删除所有组播相关的套接字配置代码,包括设置
MulticastTimeToLive、AddMembership的两行逻辑 - 删除给UDP套接字设置
NoDelay选项的无效代码 - 先使用
IPAddress.Any绑定本机所有网卡的对应端口,确认收包正常后,如果需要限定单网卡监听,再确认对应网卡确实配置了192.168.1.140的IP地址,避免因本机不存在该IP触发绑定错误。
修复后的CAA类构造函数代码如下:
public CAA() { Target_Port = 50000; try { IPEndPoint LocalHostIPEnd = new IPEndPoint(IPAddress.Any, Target_Port); UDPSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); UDPSocket.Bind(LocalHostIPEnd); Console.WriteLine("Starting Recieve"); Recieve(); } catch (Exception e) { Console.WriteLine(e.Message + " " + e.StackTrace); } }
额外优化提示:
当前接收回调中没有处理收到的有效数据,拿到bytesRead后,需要从state.buffer中截取前bytesRead长度的字节作为有效报文内容,不要直接读取整个512字节的缓冲区,避免拿到历史残留数据。
如果后续需要接收真正的组播报文,传入MulticastOption的地址必须是224.0.0.0-239.255.255.255范围内的合法组播地址,多网卡环境下建议在构造MulticastOption时指定本机对应出口的IP地址,避免网卡选择错误触发异常。
内容的提问来源于stack exchange,提问作者Muhammed Kara

