3

Bonjour를 사용하는 동일한 서비스를 사용하는 다른 장치와 연결을 설정하기 위해 GCDAsyncsocket Library를 사용하여 Singleton Class를 작성했습니다. 나는 또 다른 장치 (클라이언트) 난에서 사용할 수있는 장치를 찾아 "StartBrowsing"를 호출 오전의 응용 프로그램에서, 그것은 호스트 (서버)로 설정하려면 "startPublishing을"의 방법을 사용하고 하나 개의 장치에연결 직후 서버 연결 해제

회로망. 사용자가 해당 네트워크에서 서비스 중 하나를 선택하면 "initConnectionWithService"메서드를 호출하고 연결할 NetService의 주소를 확인하여 연결 흐름을 시작합니다.

BonjourUtilClass.h 매우 예상치 못한 일이 happending 위의 것을 실행, 클라이언트 역할을하는 장치에 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 

그러나이에 콜백을 받고있다

@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 

가 연결됨 호스트가이고 immediatly 다른 콜백이 올 것입니다. di Paulw11의 서버 장치에 클라이언트 장치

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} 

로그에

로그 dDisconnected

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) 
+1

델리게이트에 소켓에 ​​대한 참조를 어떻게 저장하고 있습니까? 당신은 강한 재산이나 iVar를 사용하고 있습니까? – Paulw11

+0

예 소켓의 모든 참조가 강합니다. 이 클래스는 싱글 톤 (singleton) 클래스이므로, 특히이 경우 참조가 발행 될 수 없다고 생각합니다. – Mrug

+0

클래스는 싱글 톤이지만 새로운 연결을 얻을 때 반환되는 소켓은 어딘가에 보관해야합니다. 싱글 톤 자체는 연결된 소켓에 대한 참조를 보유하지 않을 것입니다. – Paulw11

답변

3

코멘트 솔루션을 찾기 위해 저를 도왔다. 사실 클라이언트쪽에 Socket을 저장했지만, 콜백 메소드 "didAcceptNewSocket"을 가져 오는 새로운 소켓에 대한 참조를 저장하는 것을 잊어 버렸습니다.

그래서 didAcceptNewSocket 방법은 다음과 같아야 newSocket이 방법에서 수신되도록
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{ 
    NSLog(@"Accepted new Socket: HOST : %@ , CONNECTION PORT :%li",newSocket.connectedHost,(long)newSocket.connectedPort); 
    socketConnected = newSocket; 
} 

추가 통신을 유지할 수있다. 이전의 경우에는 메소드가 끝날 때 해제되었습니다.