UPnP组播:缺less来自M-SEARCH(发现)的答案

我创build了一个小程序来testingUPnP多播(Visual C#2010 Express,在Windows 7 Professional 64位上运行)。 我可以从我的networking中的UPnP设备收到UPnP NOTIFY消息。 但是当我发送M-SEARCH消息时,我没有得到答案。

我已经在iOS环境(Monotouch for iOS,在Mac上的iPhone模拟器上运行)上testing了相同的代码。 在那里它运行良好,我从我的UPnP设备得到所有的search响应。 我也可以从我的Windows程序中看到M-SEARCH消息。

它看起来像Windows(或防火墙?)隐藏search响应。 任何想法?

这里是代码:

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)); } } } 

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

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

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

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

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

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

对于后人:设置上述所有选项对于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); 

所以不要这样做。