美文网首页
粘包、半包

粘包、半包

作者: 一个半吊子工程师 | 来源:发表于2020-10-23 21:17 被阅读0次

1.什么是粘包?

粘包通常出现在TCP的协议里面,对于UDP来说是不会出现粘包状况的。通俗的讲,就是在发包的时候会建立一个缓存区,发送的数据都会先进入这个缓存区,当上一条数据的接收被确认或者到达最大等待时间之后,才会将缓存区的数据一块发送过去,如此反复。将小包进行整合,避免小包多次发送造成的传输速度慢等问题。


image.png

2.什么时候才需要处理粘包?

理论上来讲,只要是基于TCP的socket链接,都需要处理粘包的情况。
  可能有些人在测试的时候并没有出现粘包的情况,认为并不需要对粘包进行处理,这种想法是错误的。

3.粘包解决方案

对于粘包,在Server端和Client端都需要解决粘包的问题,由于问题一致,所以解决方案也基本是通用的,只是相关语法需要变换一下。

使用了一个名为CocoaAsyncSocket的第三方

导入成功后,正式开始处理粘包问题。

首先,跟服务器确定数据头的问题

对于粘包,一般有两种解决方案:

  • 第一种就是服务器返回的字段中有可识别的头和尾,我们可以根据可识别的头和尾来拆包。
  • 第二种是服务器返回的数据只包含头,头里面有数据的长度,我们可以根据这个头包含的数据长度来进行拆包。本文采用的便是第二种方案。

在链接成功之后,在回调方法里面创建一个缓存区

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    self.readBuf = [[NSMutableData alloc] init];
  NSLog(@"链接成功后的其他操作");

}

然后在收到服务器发送的数据的时候,对这个数据进行处理

//服务器发送的数据
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    //将数据存入缓存区
    [self.readBuf appendData:data];
    
    //数据中前面有4个字节的头信息,其中前两位是固定的头长度(用处不大),后两位才是数据的长度。
    //如果大于4个字节证明有消息,因为服务器只要发送数据,必定包含头
    while (self.readBuf.length > 4) {
        
        //将消息转化成byte,计算总长度 = 数据的内容长度 + 前面4个字节的头长度
        Byte *bytes = (Byte *)[self.readBuf bytes];
        NSUInteger allLength = (bytes[2]<<8) + bytes[3] +4;
        
        //缓存区的长度大于总长度,证明有完整的数据包在缓存区,然后进行处理
        if (self.readBuf.length >= allLength) {
            NSMutableData *msgData = [[self.readBuf subdataWithRange:NSMakeRange(0, allLength)] mutableCopy];
            //提取出前面4个字节的头内容,之所以提取出来,是因为在处理数据问题的时候,比如data转json的时候,头内容里面包含非法字符,会导致转化出来的json内容为空,所以要先去掉再处理数据问题
            [msgData replaceBytesInRange:NSMakeRange(0, 4) withBytes:NULL length:0];
    
            NSLog(@"开始处理数据问题");

            //处理完数据后将处理过的数据移出缓存区
            _readBuf = [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(allLength, _readBuf.length - allLength)]];
        }else{
            //缓存区内数据包不是完整的,再次从服务器获取数据,中断while循环
            [self.clientSocket readDataWithTimeout:-1 tag:0];
            break;
        }
    }
    
    //读取到服务端数据值后,能再次读取
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}   

相关文章

  • 2.Netty基本--TCP粘包半包如何解决,协议和序列化到底啥

    [toc] 1.什么是TCP粘包和半包?为什么会出现粘包和半包? 粘包: 粘包半包 混合双打: 首先TCP是可靠有...

  • Netty处理半包粘包的解码思路

    Netty处理半包粘包的解码思路 前言 写netty通讯的都不免遇到半包粘包情况。那么半包粘包是什么意思呢?我们可...

  • 粘包、半包

    1.什么是粘包? 粘包通常出现在TCP的协议里面,对于UDP来说是不会出现粘包状况的。通俗的讲,就是在发包的时候会...

  • netty的编解码

    什么是拆包/粘包 TCP 粘包/拆包 半包:读取的数据不是一个数据包粘包:读取的数据超过一个数据包 粘包问题的解决...

  • Netty 半包,粘包处理

    基于TCP协议处理网络数据经常面对半包和粘包问题,那么什么是半包问题,什么是粘包问题呢?应用层消息在被发送到网络之...

  • Netty 进阶

    title: Netty 进阶date: 2021/04/06 15:28 一、黏包 & 半包 1.1 粘包现象 ...

  • Netty粘包/半包问题

    在netty中经常会出现粘包/半包问题? 1.应用程序写入的数据大于套接字缓冲区大小, 这将导致半包现象2.应用程...

  • TCP 半包粘包问题

    什么是粘包现象 TCP 粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着...

  • netty-半包&粘包

    what? 在Netty发送和读取数据时,场所实际是ByteBuf缓冲区。 每一次发送就是向通道写入一个ByteB...

  • 即时通讯

    iOS即时通讯,从入门到“放弃”?socket的半包,粘包与分包的问题iOS 处理socket粘包问题iOS___...

网友评论

      本文标题:粘包、半包

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