2012-10-09 22 views
11

Ich habe ein kleines Programm zum Testen von UPnP Multicast (Visual C# 2010 Express, läuft unter Windows 7 Professional 64 Bit) erstellt. Ich kann UPnP-Nachrichten von UPnP-Geräten in meinem Netzwerk empfangen. Aber wenn ich die M-SEARCH Nachricht sende, bekomme ich keine Antworten.UPnP Multicast: fehlende Antworten von M-SEARCH (Discovery)

Ich habe den gleichen Code auf einer iOS-Umgebung (Monotouch für iOS, läuft auf einem iPhone-Simulator auf einem Mac) getestet. Da läuft es gut und ich bekomme alle Suchantworten von meinen UPnP-Geräten. Ich kann auch die M-SEARCH-Nachricht von meinem Windows-Programm sehen.

Es sieht aus wie Windows (oder eine Firewall?) Die Suchantworten versteckt. Irgendeine Idee? Hier

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

Wofür ist MulticastEndPoint eingestellt? – simonc

+0

Sind Sie sicher, dass die M-SEARCH, die Sie auf iOS sehen, die von Ihrem Windows-Programm ist? Haben Sie ein anderes UPnP-Erkennungstool in Ihrer Windows-Box ausprobiert? –

+0

@PavelZdenek: Ja bin ich mir sicher. Ich habe einige zusätzliche Zeichen an die M-SEARCH-Nachricht angehängt, damit ich die Nachricht auf iOS erkennen konnte. –

Antwort

15

Ja, ich das Problem gelöst! Kleiner Fehler, große Auswirkung:

Mein Programm sendet den M-SEARCH auf Port 1900, der an die UPnP-Multicast-Gruppe gebunden ist. Da ich den LocalEndPoint an denselben Port gebunden habe, antworten die UPnP-Geräte mit Unicast auf Port 1900. Auf iOS funktionierte das, weil mein Programm der einzige Dienst war, der an diesen Port gebunden war. Aber auf dem PC habe ich mehrere Dienste gefunden, die an Port 1900 gebunden sind (gefunden mit "netstat -p UDP -a"). So wurden die Unicast-Nachrichten von den UPnP-Geräten von einem der anderen Dienste absorbiert.

Die Lösung: Ich habe den LocalEndPoint an einen freien Port (z. B. 60000) gebunden, und jetzt funktioniert es gut!

+1

Sie waren schneller als ich :-) Ja, Windows standardmäßig führt SSDP-Dienst. Werfen Sie einen Blick auf die Option netstat -b –

+0

Ich habe das gleiche Problem, aber ich kann meinen Port nicht ändern. Gibt es eine andere Möglichkeit, dieses Problem zu beheben? – Kingpin

+3

Binden Sie nicht an einen bestimmten Port (60000), fragen Sie einfach nach einem ephemeren (0)! Oder eines Tages kann dies fehlschlagen, weil jemand anderes 60000 verwendet –

4

Beim Erstellen des lokalen Endpunkts verwenden Sie Port 0 (Null), um einen freien Port zu binden, der keinen festen Port verwendet. Ein weiterer Punkt entdeckt. Binding IPAddress.Any oder IPAddress.Loopback erhalten Antworten von Microsoft (lokal?) System, wo als Bindung an eine der LAN-Adresse (n) Antworten aus dem lokalen Netz erhalten.

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

Es gibt keine wirkliche Grenze zu IPV4, ich habe die IP V6 Multicast-Adressen gefunden FF02 :: C (link-local), FF05 :: C (site-local), FF08 :: C (organisationslokal) und FF0E :: C (global). Beachten Sie, dass der Gültigkeitsbereich von IP V4 standortlokal ist. Gefunden bei [Wikipedia - SSDP] (https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol) – VBWebProfi

+0

'' Environment.GetEnvironmentVariable ("COMPUTERNAME") '' kann durch '' Environment.MachineName'' ersetzt werden. – VBWebProfi

1

für die Nachwelt: erste IPv4-Adresse bekommen kann wie dies getan werden, um diese Optionen alle oben Einstellung für M-SEARCH nicht erforderlich ist, und kann sogar kontraproduktiv sein:

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

Also nicht TU es.