简体   繁体   English

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

[英]Disconnecting with server immediately after connecting

I have written a Singleton Class using GCDAsyncsocket Library to establish connection with any other device having same service using Bonjour. 我使用GCDAsyncsocket Library编写了一个Singleton类,以使用Bonjour与任何其他具有相同服务的设备建立连接。

On one device I am using its Method " startPublishing " to make it a Host(Server), from the Application on another Device(Client) I am calling " StartBrowsing " to find out the available Devices in Network. 在一台设备上,我使用其方法“ startPublishing ”使其成为主机(服务器),从另一台设备(客户端)上的应用程序调用“ StartBrowsing ”来查找网络中的可用设备。 When user selects any of service in that Network I am calling method " initConnectionWithService ", that initiate Connection flow by resolving address of NetService to connect. 当用户选择该网络中的任何服务时,我正在调用方法“ initConnectionWithService ”,即通过解析NetService的地址来连接来启动Connection流。

BonjourUtilClass.h 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 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

But, On execution of above things very unexpected things happending, Device which is acting as Client is getting callback in didConnectedToHost and immediatly, another Callback is coming that is in didDisconnected 但是,在执行上述非常意外的事情时,充当客户端的设备正在didConnectedToHost中进行回调,并立即进行另一个回调即将来自didDisconnected

Logs on Client Device 登录客户端设备

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}

Logs On Server Device 登录服务器设备

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)

Comment of Paulw11 Helped me to find out the Solution. 对Paulw11的评论帮助我找到了解决方案。 Actually I stored Socket on client side, but forgot to Store reference of new Socket getting in callback method "didAcceptNewSocket". 实际上我在客户端存储了Socket,但是忘了存储新Socket的引用获取回调方法“didAcceptNewSocket”。

So the Method didAcceptNewSocket should be as below: 所以方法didAcceptNewSocket应如下所示:

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

So that newSocket received in this method can be persist for further communication. 因此,在此方法中接收的newSocket可以持续进行进一步的通信。 In earlier case it was releasing at end of method. 在早先的案例中,它是在方法结束时发布的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM