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];