【问题标题】:NSNetServiceBrowser does not find ServiceNSNetServiceBrowser 找不到服务
【发布时间】:2013-06-21 11:37:42
【问题描述】:

我尝试基于 CocoaEcho 示例编写客户端(iPad)/服务器(iMac)应用程序。我的第一个简单示例有效,但在添加更多功能后,客户端无法找到服务器。

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

1) 我检查了服务器是否可以通过 WiTap 应用程序访问。客户端和服务器连接正确。

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

3) 客户端应用程序中的 nsnetservicebrowser 对象被声明为属性,因此不应该存在范围问题。我还检查了调试器,它仍然存在....

我的代码:

客户:

    @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;
}

【问题讨论】:

    标签: ios objective-c bonjour nsnetservice nsnetservicebrowser


    【解决方案1】:

    除非我断开连接并重新连接(即使是第一次),否则我一直都收到 -72003 错误。这导致了这个解决方案:

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

    我不知道为什么会这样,但我不再收到错误消息。

    【讨论】:

      【解决方案2】:

      我有类似的问题。我的代码成功注册了 NSNetService 并启动了 NSNetServiceBrowser 但无法 -resolveWithTimeout 其他设备。奇怪,但有时确实有效,有时无效,有时不对称。

      经过大量调试后,我可以给你一些检查提示:

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

      2. 尝试使用不同的 WiFi 热点。奇怪,但我的主要 WiFi 性能很差。在我切换到另一个之后,它使用相同的代码就像一个魅力。尝试从互联网上拔下 WiFi 进行测试。

      3. 您可以向从 API 返回的对象(如 NSNetService)添加一些保留(或分配给静态变量)。如果 ARC 决定不再需要对象,它可以静默地解除分配。这有助于我进行一些测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-09
        相关资源
        最近更新 更多