2

私はiPhoneアプリの設計を学び始めたばかりで、クラ​​イアントサーバー環境をセットアップしようとしています。まず、公開するサービスがクライアントに表示されることを確認したいと思います。私はAppleのドキュメントの助けを借りてサーバーとクライアントのコードを書きました。ただし、サービスが公開されているにもかかわらず(netServiceWillPublish(NSNetService *)senderが呼び出されている)、クライアントがこのサービスを識別していないことがわかりました。クライアント側では、デリゲート関数netServiceBrowserWillSearch:(NSNetServiceBrowser *)browserが呼び出され、クライアントがサービスを検索していると思わせます。ただし、didFindServiceデリゲート関数が呼び出されることはありません。なぜこれが機能しないのか、私は困惑しています。私はさまざまな場所からクライアント側のサンプルコードをフォローしましたが、私のコードはそれらのコードと一致しています。

また、私は次の質問があります

  1. サービス名(トランスポートレベルプロトコルに付属)は任意の文字列にすることができますか?または、http://www.dns-sd.org/ServiceTypes.htmlで指定する必要がありますか。また、サービスディスカバリとは別に、これはどのような目的を解決しますか。

  2. サーバー側でNSNetServiceオブジェクトの詳細を印刷すると(ソケットを設定してサービスを開始した後)、ホスト名が(null)として印刷され、アドレスが表示されません。技術的には、サービスが開かれるときに、これらを値に設定するべきではありませんか?はいの場合、誰かが私のコードのどこが間違っているのか教えてください。

サービスの公開と参照が行われるプロジェクトのクライアントとサーバーのコードブロックを添付しました。私はこの問題で私の仕事に行き詰まっているので、助けは非常にありがたいです。

これは、サービスを参照するクライアント側のコードスニペットです

NSNetServiceBrowser *serviceBrowser;
serviceBrowser = [[NSNetServiceBrowser alloc] init];
[serviceBrowser setDelegate:self];
[serviceBrowser searchForServicesOfType:@"_http._tcp." inDomain:@"local."];

これは、サービスを公開するサーバー側のコードスニペットです

BOOL                success;
int                 fd;
int                 err;
int                 junk;
struct sockaddr_in  addr;
NSInteger           port;

port = 0;

fd = socket(AF_INET, SOCK_STREAM, 0);
success = (fd != -1);
if(success) {
    memset(&addr, 0, sizeof(addr));
    addr.sin_len = sizeof(addr);
    addr.sin_family = AF_INET;    
    addr.sin_port = 0;
    addr.sin_addr.s_addr = INADDR_ANY;
    err = bind(fd, (const struct sockaddr*) &addr, sizeof(addr));
    success = (err == 0);
}

if (success) {
    err = listen(fd, 5);
    success = (err == 0);
}

if (success) {
    socklen_t addrLen;
    addrLen = sizeof(addr);
    err = getsockname(fd, (struct sockaddr *) &addr, &addrLen);
    success = (err == 0);

    if (success) {
        assert( addrLen = sizeof(addr));
        port = ntohs(addr.sin_port);
    }
}

if (success) {
    CFSocketContext context = { 0, (__bridge void *) self, NULL, NULL, NULL };

    assert(self->_listeningSocket == NULL);
    self->_listeningSocket = CFSocketCreateWithNative(NULL, fd, kCFSocketAcceptCallBack, AcceptCallBack, &context);

    success = (self->_listeningSocket != NULL);

    if (success) {
        CFRunLoopSourceRef rls;
        fd = -1;    //listeningSocket is now responsible for closing the socket
        rls = CFSocketCreateRunLoopSource(NULL, self.listeningSocket, 0);
        assert(rls != NULL);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
        CFRelease(rls);
    }
}

if (success) {
    self.netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_http._tcp." name:@"test" port:port];
    success = (self.netService != nil);
}
if (success) {
    self.netService.delegate = self;
    [self.netService publishWithOptions:NSNetServiceNoAutoRename];

}

if (success) {
    assert(port != 0);
    [self serverDidStartOnPort:port];
}
else {
    [self stopServer:@"Start Failed"];
    if (fd != -1) {
        junk = close(fd);
        assert(junk == 0);
    }
}

これは、サービスが公開されていることを通知し、NSSocketオブジェクトの詳細を出力するコードスニペットです。

- (void)netServiceWillPublish:(NSNetService *)sender {
    NSLog(@"This function is getting called");
    NSLog(@"sender.name %@",sender.name);
    NSLog(@"sender.addresses %@",sender.addresses);
    NSLog(@"sender.domain %@",sender.domain);
    NSLog(@"sender.hostname %@",sender.hostName);
    NSLog(@"sender.type %@",sender.type);
    NSLog(@"sender.port %d",sender.port);
}

ありがとう
Vivek

4

0 に答える 0