NSStream - 无法完成操作。拒绝连接

时间:2012-10-12 07:30:32

标签: objective-c cocoa nsstream nsnetservice

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

我第一次在 Device A 上启动服务并尝试打开输入/输出流,一切都按预期工作。如果我然后退出 Device A 上的应用并重新打开它,则会创建服务(因为netServiceDidPublish被调用)但是当我再次尝试打开流时,我得到以下错误域= NSPOSIXErrorDomain代码= 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;

}

希望这就够了。提前致谢

1 个答案:

答案 0 :(得分: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];