UPnP 多播:M-SEARCH 缺少答案(发现)

Posted

技术标签:

【中文标题】UPnP 多播:M-SEARCH 缺少答案(发现)【英文标题】:UPnP Multicast: missing answers from M-SEARCH (Discovery) 【发布时间】:2012-09-29 11:21:29 【问题描述】:

我创建了一个小程序来测试 UPnP 多播(Visual C# 2010 Express,在 Windows 7 Professional 64 位上运行)。我可以从我的网络中的 UPnP 设备接收 UPnP 通知消息。但是当我发送 M-SEARCH 消息时,我没有得到任何答案。

我在 ios 环境(iOS 的 Monotouch,在 Mac 上的 iPhone 模拟器上运行)测试了相同的代码。它在那里运行良好,我从我的 UPnP 设备中获得了所有搜索响应。我还可以从我的 Windows 程序中看到 M-SEARCH 消息。

看起来 Windows(或防火墙?)正在隐藏搜索响应。有什么想法吗?

代码如下:

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 1900);
IPEndPoint MulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);

Socket UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.Bind(LocalEndPoint);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

Console.WriteLine("UDP-Socket setup done...\r\n");

string SearchString = "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";

UdpSocket.SendTo(Encoding.UTF8.GetBytes(SearchString), SocketFlags.None, MulticastEndPoint);

Console.WriteLine("M-Search sent...\r\n");

byte[] ReceiveBuffer = new byte[64000];

int ReceivedBytes = 0;

while (true)

    if (UdpSocket.Available > 0)
    
        ReceivedBytes = UdpSocket.Receive(ReceiveBuffer, SocketFlags.None);

        if (ReceivedBytes > 0)
        
            Console.WriteLine(Encoding.UTF8.GetString(ReceiveBuffer, 0, ReceivedBytes));
        
    

【问题讨论】:

MulticastEndPoint 设置为什么? 您确定您在 iOS 上看到的 M-SEARCH 是来自您的 Windows 程序的那个吗?您是否在 Windows 机器上尝试过其他 UPnP 发现工具? @PavelZdenek:是的,我确定。我在 M-SEARCH 消息上附加了一些额外的字符,以便我可以在 iOS 上识别该消息。 【参考方案1】:

是的,我解决了这个问题!小错误,大影响:

我的程序在绑定到 UPnP 多播组的端口 1900 上发送 M-SEARCH。因为我将 LocalEndPoint 绑定到同一个端口,UPnP 设备以单播方式响应端口 1900。在 iOS 上它可以工作,因为我的程序是唯一绑定到该端口的服务。但是在 PC 上,我发现了几个绑定到端口 1900 的服务(使用“netstat -p UDP -a”找到)。因此,来自 UPnP 设备的单播消息被其他服务之一吸收。

解决方案:我将 LocalEndPoint 绑定到一个空闲端口(例如 60000),现在它可以正常工作了!

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);

【讨论】:

你比我快 :-) 是的,Windows 默认运行 SSDP 服务。看看 netstat 选项 -b 我有同样的问题,但我无法更改我的端口。有没有其他方法可以解决这个问题? 不要绑定到特定端口(60000),只要求一个临时端口(0)!或者有一天这可能会失败,因为其他人正在使用 60000【参考方案2】:

在创建本地端点时,使用端口 0(零)绑定不使用固定端口的空闲端口。又发现了一点。绑定 IPAddress.Any 或 IPAddress.Loopback 从 Microsoft(本地?)系统获取响应,其中绑定到 LAN 地址之一从本地网络获取响应。获取第一个 IPV4 地址可以这样完成:

IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();

【讨论】:

IPV4 没有真正的边界,我发现 IP V6 多播地址 FF02::C(本地链接)、FF05::C(本地站点)、FF08::C(组织本地)和 FF0E::C(全局)。请注意,IP V4 的范围是站点本地。发现于Wikipedia - SSDP Environment.GetEnvironmentVariable("COMPUTERNAME") 可以替换为Environment.MachineName 感谢这个。 IPAddress.Any 为我的机器返回 0.0.0.0 并且没有发送/接收任何内容(我配置了大约 30 个 *** 和其他网络适配器,这可能是原因)。【参考方案3】:

对于后代:设置上述所有这些选项对于 M-SEARCH 来说是不必要的,甚至可能适得其反:

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

所以不要这样做。

【讨论】:

以上是关于UPnP 多播:M-SEARCH 缺少答案(发现)的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 上的 SSDP

JS 错误:缺少 ) 在参数列表之后

为啥在 SSDP 中需要 NOTIFY?

通过使用 UPnP 发送广播数据包来发现路由器不起作用

1900端口问题

执行 UPNP 扫描不会返回 Philips Hue Bridge