NSNetServiceBrowser找不到服务

我试图编写基于CocoaEcho示例的客户端(iPad)/服务器(iMac)应用程序。 我的第一个简单的例子工作,但添加更多的function后,客户端无法find服务器。

启动服务器后,我启动客户端,都在本地networking。 客户端开始search服务,并为其浏览器获取“netServiceBrowserWillSearch:”消息,但之后没有任何反应。 再次触发对服务的search,导致出现错误-72003,10(浏览器仍在忙于search)的“didNotsearch:”消息。

1)我检查了服务器与WiTap应用程序可达。 有客户端和服务器连接正确。

2)我检查是否服务器发布“dns-sd -B _cocoaecho”的服务,它被检测到。

3)客户端应用程序中的nsnetservicebrowser对象被声明为一个属性,所以不应该有一个范围问题。 我也检查了debugging器,它仍然存在….

我的代码:

客户:

@interface MySocketClient : UIResponder <NSNetServiceBrowserDelegate, NSStreamDelegate> { ... NSNetService * myServer; NSString* nextMsg; } @property (nonatomic, strong, readwrite) NSMutableArray * services; // of NSNetService @property (nonatomic, strong, readwrite) NSNetServiceBrowser * serviceBrowser; @property (nonatomic, strong, readwrite) NSInputStream * inputStream; @property (nonatomic, strong, readwrite) NSOutputStream * outputStream; @property (nonatomic, strong, readwrite) NSMutableData * inputBuffer; @property (nonatomic, strong, readwrite) NSMutableData * outputBuffer; .... -(void) setup{ ... self.serviceBrowser = [[NSNetServiceBrowser alloc] init]; self.services = [[NSMutableArray alloc] init]; [self.serviceBrowser setDelegate:self]; [self.serviceBrowser searchForServicesOfType:@"_cocoaecho._tcp." inDomain:@"local."]; } - (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didNotSearch:(NSDictionary *)errorInfo { NSLog(@"%@", errorInfo); } // Sent when browsing begins - (void)netServiceBrowserWillSearch:(NSNetServiceBrowser *)browser { NSLog(@"will search \n"); } // Sent when browsing stops - (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)browser { NSLog(@"stopped search \n"); } //We broadcast the willChangeValueForKey: and didChangeValueForKey: for the NSTableView binding to work. - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing { #pragma unused(aNetServiceBrowser) #pragma unused(moreComing) NSLog(@"found a service \n"); if (![self.services containsObject:aNetService]) { [self willChangeValueForKey:@"services"]; [self.services addObject:aNetService]; [self didChangeValueForKey:@"services"]; myServer = aNetService; } } - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing { #pragma unused(aNetServiceBrowser) #pragma unused(moreComing) if ([self.services containsObject:aNetService]) { [self willChangeValueForKey:@"services"]; [self.services removeObject:aNetService]; [self didChangeValueForKey:@"services"]; } } 

和服务器:

  - (BOOL)start { assert(_ipv4socket == NULL && _ipv6socket == NULL); // don't call -start twice! CFSocketContext socketCtxt = {0, (__bridge void *) self, NULL, NULL, NULL}; _ipv4socket = CFSocketCreate(kCFAllocatorDefault, AF_INET, SOCK_STREAM, 0, kCFSocketAcceptCallBack, &EchoServerAcceptCallBack, &socketCtxt); _ipv6socket = CFSocketCreate(kCFAllocatorDefault, AF_INET6, SOCK_STREAM, 0, kCFSocketAcceptCallBack, &EchoServerAcceptCallBack, &socketCtxt); if (NULL == _ipv4socket || NULL == _ipv6socket) { [self stop]; return NO; } static const int yes = 1; (void) setsockopt(CFSocketGetNative(_ipv4socket), SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(yes)); (void) setsockopt(CFSocketGetNative(_ipv6socket), SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(yes)); // Set up the IPv4 listening socket; port is 0, which will cause the kernel to choose a port for us. struct sockaddr_in addr4; memset(&addr4, 0, sizeof(addr4)); addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_port = htons(0); addr4.sin_addr.s_addr = htonl(INADDR_ANY); if (kCFSocketSuccess != CFSocketSetAddress(_ipv4socket, (__bridge CFDataRef) [NSData dataWithBytes:&addr4 length:sizeof(addr4)])) { [self stop]; return NO; } // Now that the IPv4 binding was successful, we get the port number // -- we will need it for the IPv6 listening socket and for the NSNetService. NSData *addr = (__bridge_transfer NSData *)CFSocketCopyAddress(_ipv4socket); assert([addr length] == sizeof(struct sockaddr_in)); self.port = ntohs(((const struct sockaddr_in *)[addr bytes])->sin_port); // Set up the IPv6 listening socket. struct sockaddr_in6 addr6; memset(&addr6, 0, sizeof(addr6)); addr6.sin6_len = sizeof(addr6); addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(self.port); memcpy(&(addr6.sin6_addr), &in6addr_any, sizeof(addr6.sin6_addr)); if (kCFSocketSuccess != CFSocketSetAddress(_ipv6socket, (__bridge CFDataRef) [NSData dataWithBytes:&addr6 length:sizeof(addr6)])) { [self stop]; return NO; } // Set up the run loop sources for the sockets. CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _ipv4socket, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), source4, kCFRunLoopCommonModes); CFRelease(source4); CFRunLoopSourceRef source6 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _ipv6socket, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), source6, kCFRunLoopCommonModes); CFRelease(source6); assert(self.port > 0 && self.port < 65536); self.netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_cocoaecho._tcp." name:@"" port:(int) self.port]; [self.netService publishWithOptions:0]; return YES; } 

我只是越来越-72003错误,除非我断开连接并重新连接(甚至是第一次)。 这导致了这个解决scheme:

 private let serviceBrowser = NSNetServiceBrowser() serviceBrowser.stop() serviceBrowser.searchForServicesOfType(TYPE, inDomain: DOMAIN) 

我不知道为什么这个工程,但我不再得到错误。

我有类似的问题。 我的代码成功地注册了NSNetService并启动了NSNetServiceBrowser,但不能parsing其他设备。 奇怪,但有时候做工,有时候不行,有时候不对称。

激烈的debugging后,我可以给你一些技巧来检查:

  1. 在桌面上安装Bonjour浏览器。 拔出网线并检查是否连接到与移动设备相同的WiFi热点。 在这里,您应该看到与移动设备相同的服务状态。

  2. 尝试不同的WiFi热点。 奇怪,但我主要的WiFiperformance糟糕。 在我切换到另一个后,它使用相同的代码就像一个魅力。 尝试从互联网上拔掉WiFi进行testing。

  3. 你可以添加一些保留(或分配给静态variables)从API返回的对象(如NSNetService)。 如果ARC决定不再需要对象,ARC可以默默地执行dealloc。 这有助于我的一些testing。