2010-07-07 11 views
7

Ich muss in der Lage sein, eine UDP-Nachricht zu senden und auch eine zu empfangen, um SSDP-Geräte im Netzwerk vom iPhone zu entdecken.SSDP auf dem iPhone

Ich weiß, dass ich das Paket an die Multicast-Adresse und meine HTTP-Anfrage in etwa so aussehen muss senden:

M-SEARCH * HTTP/1.1 
Host: 239.255.255.250:1900 
Man: ssdp:discover 
Mx: 3 
ST: "urn:schemas-upnp-org:device:InternetGatewayDevice:1" 

Aus der Lektüre des docs es scheint, dass ich das alles mit CFNetwork tun kann, und trotz des Lesens (und erneutes Lesen der Dokumente) habe ich Probleme damit anzufangen. Kann jemand empfehlen und Tutorials oder Code-Schnipsel, um mich über den anfänglichen Lernhöcker zu bekommen?

Ich habe die CFNetwork Programmführer bekam:

http://developer.apple.com/mac/library/documentation/Networking/Conceptual/CFNetwork/CFNetwork.pdf

und Beej Leitfaden für Netzwerkprogrammierung mit Internet-Sockets:

http://beej.us/guide/bgnet/

Dank

Dave

P.S.

Ich kann keine der Bibliotheken und Frameworks von Drittanbietern in diesem Fall verwenden.

Antwort

2

OK, endlich fertig. Ich habe eine Klasse in der Public Domain (danke Chris) namens AsyncUdpSocket gefunden, mit der du einen UDP-Socket erstellen kannst, mit dem du die Broadcast-Funktion aktivieren und der Multicast-Adresse beitreten kannst.

Es gibt eine nette Methode sendData, komplett mit Hinzufügen zu einer Laufschleife, um Blockierungen zu verhindern.

Hoffe, dass hilft.

Dave

4

Ich habe den folgenden Code für SSDP-Suche in meiner App:

-(void)discoverDevices { 
ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self]; 
[ssdpSock enableBroadcast:TRUE error:nil]; 
NSString *str = @"M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nST: mydev\r\n\r\n";  
[ssdpSock bindToPort:0 error:nil]; 
[ssdpSock joinMulticastGroup:@"239.255.255.250" error:nil]; 
[ssdpSock sendData:[str dataUsingEncoding:NSUTF8StringEncoding] 
     toHost: @"239.255.255.250" port: 1900 withTimeout:-1 tag:1]; 
[ssdpSock receiveWithTimeout: -1 tag:1]; 
[NSTimer scheduledTimerWithTimeInterval: 5 target: self 
      selector:@selector(completeSearch:) userInfo: self repeats: NO]; } 


-(void) completeSearch: (NSTimer *)t { 
NSLog(@"%s",__FUNCTION__); 
[ssdpSock close]; 
ssdpSock = nil;} 

- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{ 
NSLog(@"%s %d %@ %d",__FUNCTION__,tag,host,port); 
NSString *aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
NSLog(@"%@",aStr);} 

Es nutzt die AsyncUdpSocket von CocoaAsyncSocket.

+4

Hallo Savvybud, sieht gut aus, aber von der Spitze meines Kopfes (es war eine Weile her, dass ich das getan habe) Ich denke, dein Problem liegt bei der BindToPort. Ich bin ziemlich sicher, dass dies der Port ist, an den Rückmeldungen gesendet werden und nicht 1900 sein sollten, da dies für Multicasts reserviert ist. Wenn Sie dies auf Null setzen, wird das System eins zuweisen und es sollte funktionieren. sendData sieht gut aus. –

+0

Magic Bullet Dave, du bist der Mann! – savvybud

4

Ich habe AsyncUdpSocket erfolgreich verwendet, um SSDP-Discovery auszuführen und Controller zu finden. Hier sind meine Code-Schnipsel:

initialisieren und Einrichtung der Buchse:

// AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self]; 
    AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initIPv4]; 
    [ssdpSock setDelegate:self]; 

Beachten Sie die erste Zeile als Kommentar gekennzeichnet. Ich habe auf der AsyncUdpSocket forums einige Probleme mit Duplikaten gefunden. Ich glaube nicht, dass ich ihnen gegenüber stand, aber ich habe es trotzdem getan.

Ich habe die Fehlerprüfung, und es war nützlich, weil ich während meiner Debuggen nicht schließen Sockets wurde und ich begann sich Fehler Buchse Setup:

NSError *socketError = nil; 

    if (![ssdpSock bindToPort:1900 error:&socketError]) { 
     NSLog(@"Failed binding socket: %@", [socketError localizedDescription]); 
     return statusController; 
    } 

    if(![ssdpSock joinMulticastGroup:@"239.255.255.250" error:&socketError]){ 
     NSLog(@"Failed joining multicast group: %@", [socketError localizedDescription]); 
     return statusController; 
    } 

    if (![ssdpSock enableBroadcast:TRUE error:&socketError]){ 
     NSLog(@"Failed enabling broadcast: %@", [socketError localizedDescription]); 
     return statusController; 
    } 

    [ssdpSock sendData:[self.discoverControllerString dataUsingEncoding:NSUTF8StringEncoding] 
       toHost:@"239.255.255.250" 
        port:1900 
      withTimeout:2 
        tag:1]; 

Beachten Sie die Änderungen, die ich zu der Zeit heraus gemacht haben. Und dann endlich das Empfangs-Setup und schloss den Socket. Notieren Sie den Socket schließen. Da ich in meiner eigenen Klasse bin, wenn ich das hier ausführe - der obige Code funktionierte nicht für mich.

Die wichtigste Änderung war wahrscheinlich "NEIN", wenn ich meinen Controller nicht gefunden habe. Der erste Empfang war übrigens die Entdeckungsnachricht selbst zurückkommen. Und wenn ich die AsyncUdpSocket.h-Datei sorgfältig durchlese - "NO" zurückschicke, wenn es sich nicht um ein Paket handelt, nach dem Sie gesucht haben.

Beachten Sie auch, dass ich ARC in meinem Code verwende, aber ich kompilierte die AsyncUdpSocket ohne ARC-Unterstützung.

+0

Ich benutze den oben beschriebenen Ansatz, um eine Sony Action Cam zu entdecken. In der Zeile [ssdpSock bindToPort: 1900 Fehler: & socketError] erscheint auf dem Debugger CFSocketSetAddress listen failure: 102, aber alles ist in Ordnung, Entdeckung geschieht erfolgreich. Was zum Teufel bedeutet dieses Versagen: 102 Ich weiß es nicht. Irgendjemand eine Idee? PS: Wenn ich ein wenig tiefer graben, ist die Zeile, wo es passiert ist CFSocketError Fehler = CFSocketSetAddress (theSocket4, (__bridge CFDataRef) Adresse4); Fehlerwert ist kCFSocketSuccess –