SSDP设备网络发现无响应:两种实现均未收到UPnP设备回复
局域网UPnP设备搜索无响应问题排查
问题背景
我尝试在局域网内搜索UPnP设备,分别基于UdpClient和原生Socket实现了代码,但始终无法收到任何设备响应。
UdpClient实现代码
using (UdpClient udpClient = new()) { udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 0)); IPAddress multicastAddress = IPAddress.Parse("239.255.255.250"); udpClient.JoinMulticastGroup(multicastAddress); byte[] requestBytes = Encoding.UTF8.GetBytes("M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nST: ssdp:all\r\nMX: 3\r\n\r\n"); IPEndPoint remoteEndPoint = new(multicastAddress, 1900); await udpClient.SendAsync(requestBytes, requestBytes.Length, remoteEndPoint); DateTime startTime = DateTime.Now; while (DateTime.Now - startTime < timeout) { try { UdpReceiveResult result = await udpClient.ReceiveAsync(). WithTimeout(timeout - (DateTime.Now - startTime)); string response = Encoding.UTF8.GetString(result.Buffer); // here we parse the response... } } }
现象:udpClient.ReceiveAsync始终等待至超时返回,无任何响应数据。
原生Socket实现代码
IPEndPoint localEndPoint = new(IPAddress.Any, 0); IPEndPoint ssdpEndPoint = new(IPAddress.Parse("239.255.255.250"), 1900); using (Socket udpSocket = new(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpSocket.Bind(localEndPoint); udpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ssdpEndPoint.Address, IPAddress.Any)); udpSocket.SendTo(Encoding.ASCII.GetBytes("M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nST: ssdp:all\r\nMX: 3\r\n\r\n"), ssdpEndPoint); byte[] buffer = new byte[4096]; DateTime thresholdTime = DateTime.UtcNow.Add(timeout); while (thresholdTime > DateTime.UtcNow) { if (udpSocket.Available > 0) { EndPoint remote = new IPEndPoint(IPAddress.Any, 0); int size = udpSocket.ReceiveFrom(buffer, ref remote); // here we parse the response } } }
现象:udpSocket.Available始终为0,未收到任何数据。
疑问解答
1. 局域网内无UPnP设备时,是否会收到“空列表”响应?
不会。SSDP协议没有定义“空响应”机制,没有匹配的设备时,接收逻辑会一直等待直到超时。只有存在符合条件的UPnP设备,且设备成功接收并处理M-SEARCH请求后,才会主动向请求端口发送单播响应。
2. 现有请求的潜在问题
结合代码和SSDP协议规范,可能存在以下问题:
- 多网卡环境的组播绑定问题:代码使用
IPAddress.Any绑定端口,若机器存在多网卡(如有线+无线),组播包可能仅被某一张网卡接收,或设备响应无法正确路由到监听端口。建议指定具体的本地网卡IP加入组播,而非IPAddress.Any。 - 编码不一致:UdpClient使用UTF8编码,Socket使用ASCII编码。SSDP协议默认采用ASCII编码,部分设备对编码敏感,建议统一使用ASCII编码发送请求。
- Socket接收逻辑缺陷:原生Socket实现中依赖
udpSocket.Available轮询,该属性存在感知延迟,若响应在两次轮询间隙到达,可能会被遗漏。建议改用ReceiveFromAsync异步接收,或设置Socket超时时间后同步接收,避免轮询漏包。 - 防火墙/权限拦截:Windows防火墙可能拦截UPnP的UDP数据包,需确保应用拥有“专用网络”访问权限,可临时关闭防火墙测试。
- 组播TTL设置:默认组播TTL值为1,在复杂局域网环境下可能无法覆盖所有设备,建议设置Socket的
MulticastTimeToLive选项为2或更高,确保数据包能到达局域网内所有设备。 - 超时时间设置:
MX字段指定设备最大延迟响应时间为3秒,需确保代码中的超时时间大于3秒,避免设备还未响应就提前终止接收逻辑。
内容的提问来源于stack exchange,提问作者ElDog
相关产品推荐
相关产品推荐

