美文网首页
iOS socket即时通讯粘包处理

iOS socket即时通讯粘包处理

作者: 雪花啤酒雪花 | 来源:发表于2017-09-19 17:56 被阅读0次

    iOS在做即时通讯类应用或游戏一般都是用sokect通讯,CFSocket是苹果提供给我们的使用Socket的方式,用起来比较麻烦,里面很多东西要自己处理。平时开发项目中首选 AsyncSocket 开源库,它帮助我们封装了很多东西。我们只需要 建立连接 设置代理、发送数据、接受数据,使用起来很方便。如果是tcp连接,那就不可避免的会遇到粘包与半包的问题。来看看如何处理:

    在设计上,每一个包带上一个length的字段,表示包的长度。这样服务器、客户端才好处理粘包问题。客户端接受到数据先把这些数据放到缓冲区,根据length字段来取正确的长度,如果数据不够这个长度就等下一个数据的到来,如果还不够 继续...要是数据多于这个长度 我们只取length的长度,剩下的放缓冲区 这个肯定是下一个包的数据,同理处理。看代码:

    1.我这里每个包前面都带了一个int型length,int型migid,


    - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

    {

           NSLog(@"接受到消息");

           [self.socket readDataWithTimeout:-1 tag:0];

           //将接受到的数据data 保留到缓冲区_bufData

           [_bufData appendData:data];

           //拿到包长,缓冲区的前4个字节为包长

           int len ;

           [_bufData getBytes:&len range:NSMakeRange(0, 4)];

           //够一个包长的数据的话 就从缓冲区取出来,这样就能拿到一个正确完整的包,不够一个包长就等下一   次接收数据放于缓冲区

           while (len<= _bufData.length) {

                  //得到每个包的数据

                   NSData *tmp = [_bufData subdataWithRange:NSMakeRange(0, len)];

     //            NSData * sercetData = [self getSecret:[tmp mutableCopy] key:self.secretKey];

                    int msgid;

                    [tmp getBytes:&msgid range:NSMakeRange(4, 4)];

                    NSLog(@"msgid:%d",msgid);

                    if (msgid <= 0)  break;

                   //转化 数据

                    [[PGSocketTransmit share] transmitMessageWith:tmp];

                  //取完这段数据,把缓冲区后面的数据移到最前面,保证每次取前4个字节 都是一个int类型的包长

                  _bufData = [_bufData subdataWithRange:NSMakeRange(len, _bufData.length -len)].mutableCopy;

                  //如果刚好取完,跳出循环

                 if (_bufData.length == 0) {

                          break;

                  }

                  else{//得到下一个包的长度,继续判断

                        [_bufData getBytes:&len range:NSMakeRange(0, 4)];

                   }

             }

    }

    2.数据传输一般是要求加密的,这里给出简单的 异或 加密,每一次连接服务器返回一个随机的int类型的key,用这个key跟发送的数据异或,当然服务器返回你的数据也是需要 用这个key异或处理的 才会得到正确的数据。把我们习惯的NSData转成byte,用指针 操作地址来处理,如下,向服务器发送数据NSdata 从服务器拿到数据NSdata 调这个方法 返回 异或 后的数据。

    - (NSData *)getSecret:(NSMutableData*)data key:(int32_t)key{

          void* bytes = data.mutableBytes;

           int length = (int)data.length;

           for (int i = 0; i < length; i += 4) {

                   int32_t value = *(int32_t*)(bytes + i);

                   value ^= key;

                   memcpy(bytes + i, &value, MIN(i + 4, length) - i);

           }

           return [[NSData alloc]initWithBytes:bytes length:length];

    }

    相关文章

      网友评论

          本文标题:iOS socket即时通讯粘包处理

          本文链接:https://www.haomeiwen.com/subject/gzkujxtx.html