NSStream - Операция не может быть завершена. В соединении отказано

Я пытаюсь соединить 2 устройства с NSNetService - Устройство A публикует сервис, и Устройство B может просматривать его и устанавливать соединение. Вчера я заметил довольно неприятную проблему.

Первый раз, когда я запускаю сервис на устройстве A и пытаюсь открыть потоки ввода / вывода, все работает как задумано. Если я затем выйду из приложения на устройстве A и снова открою его, служба будет создана (потому что вызывается netServiceDidPublish), но когда я пытаюсь снова открыть потоки, я получаю следующую ошибку Domain Domain=NSPOSIXErrorDomain Code=61 "Операция не может Соединение было отклонено. Я могу немного подождать и снова попытаться открыть приложение, и потоки откроются снова, как и предполагалось.

Я думал, что это связано с тем, что я не закрываю потоки, когда закрываю свое приложение. Вот почему я попытался закрыть потоки в -(void)applicationWillTerminate, Вызывается метод, отвечающий за закрытие, но при следующем запуске приложения я получаю те же сообщения об ошибках.

Я набросал образец кода CocoaEcho, предоставленный Apple, и я не могу найти какой-либо существенной разницы. Или я могу ошибаться.

Стоит упомянуть, что я создал синглтон-класс для публикации сервиса. Я не думаю, что это должно иметь значение, но никто не может знать. Ниже вы можете найти часть кода, который я использую для публикации сервисов, открытия потоков и закрытия потоков.

Открытый сервис:

-(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 ответ

Каждый раз, когда вы запускаете свое приложение, вы звоните -(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];
Другие вопросы по тегам