陈斌彬的技术博客

Stay foolish,stay hungry

GCDAsyncSocket 使用

在代理controller类中,实现socket的代理方法

#pragma mark - GCDAsyncSocketDelegate
// 已连接
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
  GessCoreLog(@"Connected: %@:%d", host, port);
  _status = SocketConnectionStatusConnected;
  if ([self.delegate respondsToSelector:@selector(socketConnectionDidConnectedToServer:)]) {
    [self.delegate socketConnectionDidConnectedToServer:self];
  }
  //已经连接上之后,开始读取data,调用下面的readDataToLength:withTimeout:tag:方法,在此方法中会调用到socket的代理方法: socket:didReadData:tag:方法。
  [_asyncSocket readDataToLength:self.packetHeaderLength withTimeout:self.receivingTimeoutInterval tag:TAG_FIXED_LENGTH_HEADER];
}

// 收到报文,按顺序循环接收报文头,报文体。
//此方法的第一次调用是已经连接上的方法调用的时候。会读取data,然后调用代理的此方法。此时tag就事上面的TAG_FIXED_LENGTH_HEADER,所以第一次执行读取header
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data tag:(long)tag
{
  switch (tag) {
    case TAG_FIXED_LENGTH_HEADER: { // 1.已读取报文头,计算长度后继续读取报文体
      NSString *lengthString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
      [_asyncSocket readDataToLength:[lengthString integerValue] withTimeout:self.receivingTimeoutInterval tag:TAG_RESPONSE_BODY];//继续读取数据,这次传的是TAG_RESPONSE_BODY,所以下次调用此方法的时候,执行TAG_RESPONSE_BODY部分。
    }
      break;
    case TAG_RESPONSE_BODY: // 2.已读出报文体,转发报文体,然后继续读取报文头
      if ([self.delegate respondsToSelector:@selector(socketConnection:didReceivedData:)]) {
        [self.delegate socketConnection:self didReceivedData:data];
      }

      [_asyncSocket readDataToLength:self.packetHeaderLength withTimeout:self.receivingTimeoutInterval tag:TAG_FIXED_LENGTH_HEADER]; //继续读,下次调用此方法时,tag是TAG_FIXED_LENGTH_HEADER
      break;
    default:
      break;
  }
}