私はiPhoneアプリの設計を学び始めたばかりで、クライアントサーバー環境をセットアップしようとしています。まず、公開するサービスがクライアントに表示されることを確認したいと思います。私はAppleのドキュメントの助けを借りてサーバーとクライアントのコードを書きました。ただし、サービスが公開されているにもかかわらず(netServiceWillPublish(NSNetService *)senderが呼び出されている)、クライアントがこのサービスを識別していないことがわかりました。クライアント側では、デリゲート関数netServiceBrowserWillSearch:(NSNetServiceBrowser *)browserが呼び出され、クライアントがサービスを検索していると思わせます。ただし、didFindServiceデリゲート関数が呼び出されることはありません。なぜこれが機能しないのか、私は困惑しています。私はさまざまな場所からクライアント側のサンプルコードをフォローしましたが、私のコードはそれらのコードと一致しています。
また、私は次の質問があります
サービス名(トランスポートレベルプロトコルに付属)は任意の文字列にすることができますか?または、http://www.dns-sd.org/ServiceTypes.htmlで指定する必要がありますか。また、サービスディスカバリとは別に、これはどのような目的を解決しますか。
サーバー側で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