我正在尝试将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;
}
希望这就够了。提前致谢
答案 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];