I created a small program to test UPnP Multicast (Visual C# 2010 Express, running on Windows 7 Professional 64 Bit). I can receive the UPnP NOTIFY Messages from UPnP Devices in my Network. But when i send the M-SEARCH Message, i get no Answers.
I have tested the same code on a iOS environment (Monotouch for iOS, running on a iPhone simulator on a Mac). There it runs fine and i get all the search responses from my UPnP devices. I can also see the M-SEARCH message from my windows program.
It looks like Windows (or a Firewall?) is hiding the search responses. Any idea?
Here is the code:
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));
}
}
}
Yeah, I solved the problem! Small mistake, big impact:
My program is sending the M-SEARCH on port 1900 which is bound to the UPnP multicast group. Because i bound the LocalEndPoint to the same port, the UPnP devices answers with unicast to port 1900. On iOS it worked, because my program was the only service bound to this port. But on the PC, i found several services bound to port 1900 (found with "netstat -p UDP -a"). So the unicast messages from the UPnP devices was absorbed by one of the other services.
The solution: I bound the LocalEndPoint to a free port (e.g. 60000), and now it works fine!
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);
On create of local endpoint use port 0 (zero) to bind a free port not using a fixed port. Another point discovered. Binding IPAddress.Any or IPAddress.Loopback get responses from Microsoft (local?) system where as binding to one of the LAN address(es) get responses from the local net. Getting first IPV4 address can be done like this:
IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();
For posterity: setting all these options above is unnecessary for M-SEARCH and might even be counter-productive:
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);
So don't do it.
来源:https://stackoverflow.com/questions/12794761/upnp-multicast-missing-answers-from-m-search-discovery