连接后立即断开与服务器的连接

我已经使用GCDAsyncsocket库编写了一个Singleton类,用于使用Bonjourbuild立与具有相同服务的任何其他设备的连接。

在一台设备上,我使用其方法“ startPublishing ”使其成为主机(服务器),从另一台设备(客户机)上的应用程序调用“ StartBrowsing ”来查找可用的networking设备。 当用户select该networking中的任何服务时,我正在调用方法“ initConnectionWithService ”,通过parsingNetService的地址来启动连接stream程来连接。

BonjourUtilClass.h

@interface BonjourUtilClass : NSObject<GCDAsyncSocketDelegate,NSNetServiceDelegate,NSNetServiceBrowserDelegate>{ NSNetService *netServiceToPublish; GCDAsyncSocket *socketPub; NSNetServiceBrowser *netServiceToBrowse; GCDAsyncSocket *socketSub; NSMutableArray *mutArrServices; GCDAsyncSocket *socketConnected; } +(id)sharedInstance; -(void)startPublishing; -(void)startBrowsing; -(void)initConnectionWithService:(NSNetService*)netServiceToConnect; -(void)disconnectWithCurrent; @end 

BonjourUtilClass.m

 static BonjourUtilClass *sharedObject = nil; @implementation BonjourUtilClass +(id)sharedInstance{ if(!sharedObject){ sharedObject = [[BonjourUtilClass alloc]init]; } return sharedObject; } #pragma mark - Browsing -(void)startBrowsing{ if(mutArrServices){ [mutArrServices removeAllObjects]; }else{ mutArrServices = [NSMutableArray array]; } netServiceToBrowse = [[NSNetServiceBrowser alloc]init]; netServiceToBrowse.delegate= self; [netServiceToBrowse searchForServicesOfType:@"_mrug._tcp" inDomain:@"local."]; } -(void)stopBrowsing{ } -(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing{ [mutArrServices addObject:aNetService]; if(!moreComing) { // Sort Services [mutArrServices sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]]; // Update Table View [[NSNotificationCenter defaultCenter]postNotificationName:kNotifyReloadList object:mutArrServices]; } } -(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing{ [mutArrServices removeObject:aNetService]; if(!moreComing) { // Sort Services [mutArrServices sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]]; // Update Table View [[NSNotificationCenter defaultCenter]postNotificationName:kNotifyReloadList object:mutArrServices]; } } -(void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)aNetServiceBrowser{ NSLog(@"Search browser Did STOP search.."); [self stopBrowsing]; } -(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didNotSearch:(NSDictionary *)errorDict{ NSLog(@"Search browser Did not search.."); [self stopBrowsing]; } #pragma mark - NetService Delegate -(void)startPublishing{ socketPub = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *aError; if([socketPub acceptOnPort:0 error:&aError]){ netServiceToPublish = [[NSNetService alloc]initWithDomain:@"local." type:@"_mrug._tcp" name:@"" port:socketPub.localPort]; netServiceToPublish.delegate =self; [netServiceToPublish publish]; }else{ NSLog(@"Unable To Create Socket.."); } } //NetService Delegates -(void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict{ NSLog(@"Failed To Publish : Domain=%@ type=%@ name=%@ info=%@",sender.domain,sender.type,sender.name,errorDict); } -(void)netServiceDidPublish:(NSNetService *)sender{ NSLog(@"Service Published : Domain=%@ type=%@ name=%@ port=%li",sender.domain,sender.type,sender.name,(long)sender.port); } //Resolving Address - (void)netService:(NSNetService *)service didNotResolve:(NSDictionary *)errorDict { [service setDelegate:nil]; } - (void)netServiceDidResolveAddress:(NSNetService *)service { // Connect With Service if ([self connectWithService:service]){ NSLog(@"Did Connect with Service: domain(%@) type(%@) name(%@) port(%i)", [service domain], [service type], [service name], (int)[service port]); } else { NSLog(@"Unable to Connect with Service: domain(%@) type(%@) name(%@) port(%i)", [service domain], [service type], [service name], (int)[service port]); } } #pragma mark - GCDSocket delegates -(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{ NSLog(@"Accepted new Socket: HOST : %@ , CONNECTION PORT :%li",newSocket.connectedHost,(long)newSocket.connectedPort); } -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{ NSLog(@"Socket DisConnected %s,%@,%@",__PRETTY_FUNCTION__, sock,err); if(socketPub == sock){ socketPub.delegate = nil; socketPub = nil; }else if (socketConnected == sock){ socketConnected.delegate=nil; socketConnected = nil; } } - (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port { NSLog(@"Socket Did Connect to Host: %@ Port: %hu", host, port); // Start Reading [socket readDataToLength:sizeof(uint64_t) withTimeout:-1.0 tag:0]; } #pragma mark - Connection Methods -(void)disconnectWithCurrent{ if(socketConnected){ [socketConnected disconnect]; socketConnected.delegate = nil; socketConnected = nil; } } -(void)initConnectionWithService:(NSNetService*)netServiceToConnect{ // Resolve Service [netServiceToConnect setDelegate:self]; [netServiceToConnect resolveWithTimeout:30.0]; } - (BOOL)connectWithService:(NSNetService *)service { BOOL _isConnected = NO; // Copy Service Addresses NSArray *addresses = [[service addresses] mutableCopy]; if (!socketConnected || ![socketConnected isConnected]) { // Initialize Socket socketConnected = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; // Connect while (!_isConnected && [addresses count]) { NSData *address = [addresses objectAtIndex:0]; NSError *error = nil; if ([socketConnected connectToAddress:address error:&error]) { _isConnected = YES; } else if (error) { NSLog(@"Unable to connect to address. Error %@ with user info %@.", error, [error userInfo]); } } } else { _isConnected = [socketConnected isConnected]; } return _isConnected; } @end 

但是,在执行上面的事情时,非常意外的事情发生了,作为客户端的设备在didConnectedToHost中立即得到callback,并且立即发生另一个callback,它在didDisconnected

login客户端设备

 2014-12-11 15:16:32.512 GCDSocketDemo[1419:71238] Did Connect with Service: domain(local.) type(_mrug._tcp.) name(ind506Bonjour) port(52026) 2014-12-11 15:16:32.659 GCDSocketDemo[1419:71238] Socket Did Connect to Host: 10.2.4.130 Port: 52026 2014-12-11 15:16:32.660 GCDSocketDemo[1419:71238] -[AppDelegate socketDidDisconnect:withError:],<GCDAsyncSocket: 0x7fa0a3533b90>,Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote peer" UserInfo=0x7fa0a3532f70 {NSLocalizedDescription=Socket closed by remote peer} 

login服务器设备

 2014-12-11 15:15:48.546 GCDSockrtMacDemo[1397:70851] Service Published : Domain=local. type=_mrug._tcp. name=ind506Bonjour port=52026 2014-12-11 15:16:32.585 GCDSockrtMacDemo[1397:70851] Accepted new Socket: HOST : 10.2.4.130 , CONNECTION PORT :52029 2014-12-11 15:16:32.613 GCDSockrtMacDemo[1397:70851] -[BonjourUtilClass socketDidDisconnect:withError:],(null),(null) 

Paulw11评论帮助我找出解决scheme。 其实我在客户端存储了Socket,但是忘记了存储callback方法“newAcceptNewSocket”的new Socket的引用。

所以方法didAcceptNewSocket应该如下:

 -(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{ NSLog(@"Accepted new Socket: HOST : %@ , CONNECTION PORT :%li",newSocket.connectedHost,(long)newSocket.connectedPort); socketConnected = newSocket; } 

这样在这个方法中接收到的newSocket可以坚持进一步的通信。 在早先的情况下,它是在方法结束时释放。