GCDAynscSocket简略使用-客户端

GCDAynscSocket简单使用-客户端

这是一篇介绍GCDAynscSocket客户端简单使用的文章(服务端后续添加)

背景:在这篇文章之前我对socket的了解仅限于知道有TCP、UDP两种方式,使用抓包工具时甚至看不懂抓包数据(惭愧...),所以本文介绍内容深度有限,主要介绍了一些简单用法。

在这篇文章中主要介绍:

1、使用GCDAynscSocket创建连接、发送数据、接收数据、断开连接;

2、发生数据粘包的处理。

------------------------------------------------------------------------------------

1、创建连接

GCDAynscSocket的初始化般使用两种方式:

  // aDelegate是设置的委托对象,而dq是委托所在的线程,sq是socket所在的线程。其中dp不能为空,sq可以为空

  - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;

  - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;

 

  /**
  * @brief 连接到服务器
  */
  - (void)socketConnectHost
  {

    self.socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:delegateQueue];

    NSError *error = nil;

    [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];

    [self.socket readDataWithTimeout:30 tag:100];

  }

 

连接是否成功都是在委托方法中查看的

// 连接成功的委托方法  

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port

{

  NSLog(@"连接成功了...");

}

// 连接失败或中途断开连接的委托方法

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err

{

  NSLog(@"连接失败... 断开连接了...");  

}

 

 

2、发送数据

  发送数据比较简单,调用[self.socket writeData:data withTimeout:-1 tag:1]即可

 

  /**

   *  @brief   写入字符串数据

   *  @param   sendStr 要写入的字符串

   */

  - (void)writeAndSendData:(NSString *)sendStr

  {

      NSData *data = [sendStr dataUsingEncoding: NSUTF8StringEncoding];

      [self.socket writeData:data withTimeout:-1 tag:1];

  }

 

3、接收数据

  // 在委托方法中接收数据

  - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

  {

      // 对得到的data值进行解析

      [self parseSocket:sock withData:data withTag:tag];

  }

在此处有一个疑问:

在接收数据之前,是否必须执行[self.socket readDataWithTimeout:-1 tag:100]??最初开始使用时,是必须添加的否则接收不到数据,但是现在工程中没有执行这句代码,为什么可以一直接收数据呢?

 

4、断开连接

  断开连接直接调用方法[self.socket disconnect]即可,可以在委托方法查看是否断开

  /**

   *  @brief   切断socket

   */

  -(void)cutOffSocket

  {

      [self.socket disconnect];

  }

 

5、数据粘包处理

通常在tcp中都要处理数据粘包。我使用的是给数据添加包头的方式,这也是网上比较推荐的一种方式。

思路:定义好包头协议后,在数据发送端每次发送数据之前都添加一个包头(因为是每次发送都添加,所以我认为只要能够满足解包需求包头要尽可能短)。接收端根据包头信息对接收到的数据进行拆包。

 

一个简单的包头数据:  有5个字节包含两项内容开始:字符$和数据包长度msgLen。

    char     startStr = '$';

    uint32_t msgLen;

    msgLen  = (uint32_t)(str.length + 5); 

 

在接收端接收到数据后,根据包头信息,找到开始字符$,然后读出包的长度,即可正确拆包。

在整个过程中要注意:如果发送端对数据进行了编码,那么接收端要进行相应的解码,否则会造成乱码,拆包失败。

 

总结:

在整个使用学习过程中,网络知识一窍不通,又无人指导,感觉举步维艰,还好最终实现了!回头看看前面自己绕的弯路觉得很可笑,纠结的问题更是...

且学且努力!