7

iPhoneからネットワーク上のSSDPデバイスを検出するには、UDPメッセージを送信および受信できる必要があります。

パケットをマルチキャストアドレスに送信する必要があり、HTTPリクエストは次のようになる必要があることを知っています。

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

ドキュメントを読んだところ、CFNetworkでこれをすべて行うことができるようで、読んだ(そしてドキュメントを再読した)にもかかわらず、始めるのに苦労しています。誰かが私に最初の学習のこぶを乗り越えるためのチュートリアルやコードスニペットをお勧めできますか?

CFNetworkプログラミングガイドがあります。

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

およびインターネットソケットを使用したネットワークプログラミングに関するBeejのガイド:

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

ありがとう

デイブ

PS

この場合、サードパーティのライブラリとフレームワークを使用できません。

4

3 に答える 3

4

AsyncUdpSocketを使用して、SSDPディスカバリーを実行し、コントローラーを検索しました。これが私のコードスニペットです:

ソケットを初期化してセットアップします。

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

コメントアウトされた最初の行に注意してください。AsyncUdpSocketフォーラムで、重複に関するいくつかの問題を見つけました。私は彼らに直面していたとは思いませんが、とにかくそれをしました。

エラーチェックを追加しました。デバッグ中にソケットを閉じていなかったため、ソケットのセットアップに失敗し始めたので便利でした。

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

タイムアウトに加えた変更に注意してください。そして最後に受信セットアップを行い、ソケットを閉じました。ソケットが閉じていることに注意してください。これを実行しているときは自分のクラスにいるので、上記のコードは機能しませんでした。

[ssdpSock receiveWithTimeout: 2 tag:1];
    [NSTimer scheduledTimerWithTimeInterval: 5 target: self 
                                   selector:@selector(completeSearch:) userInfo: self repeats: NO]; 





    [ssdpSock closeAfterSendingAndReceiving];

最も重要な変更は、コントローラーが見つからなかった場合に「NO」を返すことでした。最初の受信は、偶然にも発見メッセージ自体が戻ってきたことでした。また、AsyncUdpSocket.hファイルを注意深く読んだ場合、探しているパケットでない場合は「NO」が返されます。

また、コードでARCを使用していますが、ARCをサポートせずにAsyncUdpSocketをコンパイルしたことにも注意してください。

-(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 %ld %@ %d",__FUNCTION__,tag,host,port);
    NSString *aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    NSLog(@"%@",aStr);



    NSString *compareString = [aStr stringByPaddingToLength:[self.responseString length] withString:@"." startingAtIndex:0];
    //NSLog(@"%@", compareString);
    //NSLog(@"%@", self.responseString);

    if ([compareString isEqualToString:self.responseString])
    {
        NSLog(@"String Compare, Controller Found!");
        [self.controllerList addObject:aStr];
        //NSData *controllerIP = [aStr dataUsingEncoding:NSUTF8StringEncoding];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"DiscoveredController" object:nil];


        return YES;
    }

    return NO;

}
于 2012-03-02T03:51:46.707 に答える
4

アプリに SSDP 検索用の次のコードがあります。

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

CocoaAsyncSocketAsyncUdpSocketのを使用します。

于 2011-01-27T20:23:39.440 に答える
2

よし、やっとできた。AsyncUdpSocket と呼ばれるパブリック ドメイン (Chris に感謝) でクラスを見つけました。これにより、ブロードキャストをオンにしてマルチキャスト アドレスに参加できる UDP ソケットを作成できます。

ブロッキングを防ぐために実行ループに追加することで完成する、素晴らしい sendData メソッドがあります。

それが役立つことを願っています。

デイブ

于 2010-07-25T16:32:09.760 に答える