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)
델리게이트에 소켓에 대한 참조를 어떻게 저장하고 있습니까? 당신은 강한 재산이나 iVar를 사용하고 있습니까? – Paulw11
예 소켓의 모든 참조가 강합니다. 이 클래스는 싱글 톤 (singleton) 클래스이므로, 특히이 경우 참조가 발행 될 수 없다고 생각합니다. – Mrug
클래스는 싱글 톤이지만 새로운 연결을 얻을 때 반환되는 소켓은 어딘가에 보관해야합니다. 싱글 톤 자체는 연결된 소켓에 대한 참조를 보유하지 않을 것입니다. – Paulw11