2012-10-09 12 views
11

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.Multicast UPnP: risposte mancanti da M-SEARCH (Discovery)

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 di 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)); 
     } 
    } 
} 
+0

A cosa è impostato MulticastEndPoint? – simonc

+0

Sei sicuro che la M-SEARCH che vedi su iOS sia quella del tuo programma Windows? Hai provato un altro strumento di rilevamento UPnP nella tua casella di Windows? –

+0

@PavelZdenek: Sì, sono sicuro. Ho allegato alcuni caratteri in più sul messaggio M-SEARCH in modo da poter riconoscere il messaggio su iOS. –

risposta

15

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

Il mio programma sta inviando 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: ho associato LocalEndPoint a una porta libera (ad esempio 60000) e ora funziona correttamente!

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

Sei stato più veloce di me :-) Sì, Windows esegue di default il servizio SSDP. Dai un'occhiata all'opzione netstat -b –

+0

Ho lo stesso problema ma non posso cambiare la mia porta. C'è un altro modo per risolvere questo problema? – Kingpin

+3

Non associare a una porta specifica (60000), basta chiedere un effimero (0)! O un giorno questo può fallire perché qualcun altro sta usando 60000 –

4

Alla creazione di un endpoint locale utilizzare la porta 0 (zero) per collegare 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 primo indirizzo IPv4 può essere fatto in questo modo:

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

Non c'è davvero un limite a IPV4, ho trovato gli indirizzi multicast IP V6 FF02 :: C (link-local), FF05 :: C (site-local), FF08 :: C (organizzazione-locale) e FF0E :: C (globale). Si noti che l'ambito di IP V4 è local-local. Trovato su [Wikipedia - SSDP] (https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol) – VBWebProfi

+0

'' Environment.GetEnvironmentVariable ("COMPUTERNAME") '' può essere sostituito da '' Environment.MachineName''. – VBWebProfi

1

Ai posteri: impostare tutte queste opzioni di cui sopra è inutile per M-SEARCH e potrebbe persino 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); 
non

Così fallo.