2

我正在尝试将 2 个设备与 NSNetService 耦合 -设备 A发布服务,设备 B可以浏览它并建立连接。昨天我注意到一个非常讨厌的问题。

我第一次在设备 A上启动服务并尝试打开输入/输出流,一切都按预期工作。如果我然后退出设备 A上的应用程序并重新打开它,则会创建服务(因为 netServiceDidPublish 被调用)但是当我再次尝试打开流时,我得到以下错误 Domain=NSPOSIXErrorDomain Code=61“操作无法完成。连接被拒绝。然后我可以稍等片刻,然后尝试再次打开应用程序,然后流会按预期再次打开。

我认为这与我退出应用程序时没有关闭流的事实有关。这就是为什么我尝试关闭-(void)applicationWillTerminate. 负责关闭的方法被调用,但下次我启动应用程序时,我会收到相同的错误消息。

我用 Apple 提供的 CocoaEcho 示例代码涂鸦,但找不到任何主要区别。或者我可能错了。

值得一提的是,我为服务发布创建了一个单例类。我认为这无关紧要,但永远不会知道。您可以在下面找到我用于服务发布、流打开和流关闭的一些代码。

开通服务:

-(void)startServiceWithName:(NSString*)name withType:(NSString*)type {

    // init the socket
    if(_socket) {

        // socket initialized
        addr = (struct sockaddr*)[[_socket address] bytes];

        if (addr->sa_family==AF_INET) {
            // IPV4
            port = ntohs( ((struct sockaddr_in *)addr)->sin_port );
        }

        if (addr->sa_family==AF_INET6) {
            // IPV6
            port = ntohs( ((struct sockaddr_in6 *)addr)->sin6_port );
        }


    } else {

        // socket nil
        _socket = nil;
        NSLog(@"Socket init failed. Can't handle");

    }

    // init the service
    if(_socket) {

        // we have a socket
        _service = [[NSNetService alloc] initWithDomain:@"local."
                                                   type:type
                                                   name:name
                                                   port:port];

        if (_service) {

            [_service setDelegate:self];
            [_service publish];

        }

    }

}

服务已发布:

-(void)netServiceDidPublish:(NSNetService *)sender {

    NSLog(@"Service published on port %li", [sender port]);

    if(![self openStreams]) {
        NSLog(@"Could not open streams");
    }

}

打开流

-(BOOL)openStreams {

    NSInputStream *is;
    NSOutputStream *os;

    if ([_service getInputStream:&is outputStream:&os]) {

        _inputStream = is;
        _outputStream = os;

        [_inputStream setDelegate:self];
        [_outputStream setDelegate:self];
        [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [_inputStream open];
        [_outputStream open];

        return YES;
    }

    return NO;
}

关闭流

-(void)closeStreams {
    [_inputStream setDelegate:nil];
    [_outputStream setDelegate:nil];
    [_inputStream close];
    [_outputStream close];

    [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    _inputStream = nil;
    _outputStream = nil;

}

希望这已经足够了。提前致谢

4

1 回答 1

0

每次你启动你的应用程序时,你会打电话-(void)startServiceWithName:(NSString*)name withType:(NSString*)type吗?

我建议您在每次调用之前关闭流-(void)startServiceWithName:(NSString*)name withType:(NSString*)type

例如:

    [self.inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [inStream release];
    inStream = nil;

    [self.outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [outStream release];
    outStream = nil;

    [self startServiceWithName:someName withType:someType];
于 2012-10-14T01:31:38.543 回答