You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:05:17