socket closed by remote peer GCDAsyncsocket

在项目中用到GCDAsyncsocket,Mac端作为服务器,手机端作为客户端,在通信过程中,不定时出现以下错误:

error domain=gcdasyncsocketerrordomain code=7 socket closed by remote peer

排错

此错误一般由于服务端关闭而导致出错,出现此问题的一般排查步骤:

  • 服务端要将新连接的socket强引用,否则会出现此错误。

    @property (nonatomic, strong) NSMutableArray *socketsArray;
    
    - (void)viewDidLoad {
        _socketsArray = [[NSMutableArray alloc] init];
    }
    
    - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
      [_socketsArray addObject:newSocket];
      [newSocket readDataWithTimeout:-1 tag:0];
    }
    
  • 没有规律发送心跳或者心跳间隔过长。“Socket closed by remote peer” - GCDAsyncSocket Error Code 7中有人尝试将心跳从10分钟改为5分钟之后解决了此错误,可参考。由于我7秒发送一次心跳,因此排除此可能性。

  • 是否使用相同的凭证从不同的客户端登录,并且在服务器设置中有这样的设置:如果有资源冲突,立即踢出另一个资源,在服务器>服务器设置>资源策略。

排查

经过排查,发现存在以下问题:

  1. socket的代理回调队列在主线程,会影响计时,超时从而导致出现此错误。
  2. 每个socket writeData之后应没有发送readDataWithTimeout,代理不再接收数据。
  3. 定时器用NSTimer或者PerformSelectAfter两种方式可能存在问题。

解决

  1. socket的代理回调队列放在子线程。

    //启动服务
        _severPort = [OsxPortListHelper port];
        _socketDelegateQueue = dispatch_queue_create("socket_delegate_queue", NULL);//注意成员变量引用,否则会释放
        _serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_socketDelegateQueue];
        [_serverSocket acceptOnPort:_severPort error:nil];
    
  2. 每个socket writeData:之后应发送readDataWithTimeout:方法,告诉代理接收数据。

    [sock writeData:data withTimeout:-1 tag:0];
    [sock readDataWithTimeout:-1 tag:0];
    
  3. 定时器改用_sendHeartBeatTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _socketDelegateQueue);方式。

参考

socket closed by remote peer gcdasyncsocket
写网络视频监视器中的总结 (一)

你可能感兴趣的:(暴击Mac,OSX应用开发,Mac应用开发,objective-c)