UPnP Multicast: risposte mancanti da M-SEARCH (Discovery)

Ho creato un piccolo programma per testare UPnP Multicast (Visual C # 2010 Express, in esecuzione su Windows 7 Professional 64 bit). Posso ricevere i messaggi UPnP NOTIFY dai dispositivi UPnP nella mia rete. Ma quando invio il messaggio M-SEARCH, non ottengo risposte.

Ho testato lo stesso codice su un ambiente iOS (Monotouch per iOS, eseguito su un simulatore iPhone su un Mac). Lì funziona bene e ottengo tutte le risposte di ricerca dai miei dispositivi UPnP. Posso anche vedere il messaggio M-SEARCH dal mio programma Windows.

Sembra che Windows (o un firewall?) Nasconda le risposte alla ricerca. Qualche idea?

Ecco il codice:

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

Sì, ho risolto il problema! Piccolo errore, grande impatto:

Il mio programma sta inviando la M-SEARCH sulla porta 1900 che è legata al gruppo multicast UPnP. Poiché ho associato LocalEndPoint alla stessa porta, i dispositivi UPnP rispondono con unicast alla porta 1900. Su iOS ha funzionato, perché il mio programma era l’unico servizio associato a questa porta. Ma sul PC, ho trovato diversi servizi legati alla porta 1900 (trovati con “netstat -p UDP -a”). Quindi i messaggi unicast dei dispositivi UPnP sono stati assorbiti da uno degli altri servizi.

La soluzione: collegavo LocalEndPoint a una porta libera (es. 60000) e ora funziona perfettamente!

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

Alla creazione dell’endpoint locale utilizzare la porta 0 (zero) per colbind una porta libera che non utilizza una porta fissa. Un altro punto scoperto. Binding IPAddress.Any o IPAddress.Loopback ottiene risposte dal sistema Microsoft (locale?) In cui il binding a uno degli indirizzi LAN ottiene risposte dalla rete locale. Ottenere il primo indirizzo IPV4 può essere fatto in questo modo:

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

Per i posteri: l’impostazione di tutte queste opzioni sopra non è necessaria per M-SEARCH e potrebbe anche essere controproducente:

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

Quindi non farlo.