iPhone/iPadネットワークプログラミング(6)Bonjourを使ってデータを送る (4) iPhone/iPadでサービス発行

そろそろ iPhone/iPadネットワークプログラミングの続きを書かないとね。
前回のさいごに、releaseをどうやるかなどをやると書いたが、後回しにすることにした。
今回は、これまで Mac <=> iPhone/iPad であったのを iPhone/iPad <=> iPhone/iPad にしてみる。
つまり、今まで Mac で実装していたサービス発行側を iPhone/iPad で実装してみようということだ。
そのまま移行できそうなんだけど、大きな問題として、iOS SDK には NSSocketPort が存在しないのだ。Mac では NSSocketPort を使って、サービスとソケット(ポート)とハンドルを結びつけていたのだが、iPhone/iPadではその方法は使えないため、書き換える必要がある。
そこで、今回は C言語のソケットプログラミングでその部分をカバーする。


まずは、サービスを発行する。これはほとんど変わらない。NSSocketPort が無くなっただけ。

#define PORT    7000

- (void) publish
{
    NSNetService* service = [[NSNetService alloc] initWithDomain:@"" type:@"_test._tcp" name:@"NetTest" port:PORT];
    if(service){
        [service setDelegate:self];
        [service publish];
    }else{
        NSLog(@"NSNetServiece が失敗してるよ!");
    }
}

サービス発行に成功した場合の部分を実装。ここが大きく変わります。

#import <netinet/in.h>
#import <sys/socket.h>

- (void) netServiceDidPublish: (NSNetService*) sender
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_len = sizeof(addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(PORT);
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0){
        close(sock);
        NSLog(@"bindに失敗");
        return;
    }
    if(listen(sock, 1)){
        close(sock);
        NSLog(@"接続失敗");
        return;
    }

    NSFileHandle* socketHandle = [[NSFileHandle alloc] initWithFileDescriptor:sock closeOnDealloc:YES];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(acceptConnection:)
                                                 name:NSFileHandleConnectionAcceptedNotification
                                                object:socketHandle];
    [socketHandle acceptConnectionInBackgroundAndNotify];
}

C言語のソケットを使っているので、それ用のヘッダをインポートしています。あとはCのソケット通信をやる手順通りに処理を進め、listenのあとで、ソケットとファイルハンドルを結びつけます。後の部分は以前と同じで問題ないはず。


これで、端末同士で通信ができるようになったはず。次回は、実際にプロジェクトを作ってタッチした座標を送るという具体的なアプリ?(アプリといえるのか?)を作ってみることにする。そこで、releaseの問題とかも解決したい。