NSData:dataWithBytes:length:详解 TCP/UDP/Socket粘包处理

先上代码

    NSString *str = @"i'm a test string";
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    NSInteger dataLength = data.length;
    NSData *lengthData = [NSData dataWithBytes:&dataLength length:8];
    NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0, 4)];

    NSInteger getDataLength = 0;
    [newLengthData getBytes:&getDataLength length:sizeof(getDataLength)];
    
    
    NSInteger getDataLength1 = 0;
    [lengthData getBytes:&getDataLength1 length:8];

这里解释一下代码:

NSData *lengthData = [NSData dataWithBytes:&dataLength length:8];

整行代码表示将dataLength长度信息转换成NSData二进制数据,这里的8表示生成一个8字节的容量,
&dataLength&是取地址符。
有时候你还能见到这种写法:
NSData *lengthData = [NSData dataWithBytes:&dataLength length:sizeof(dataLength)];
其实意思是一样的,因为NSInteger在iOS里占8个字节

接下来:
NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0, 4)];
这个意思是截取前4个字节,为什么只接前4个字节?因为大部分情况下前4个字节就是完整的信息,后面4个字节全是0,试了将MAX_INT转成data,前4个字节也完全可以存储完整的信息。

最后:

    NSInteger getDataLength1 = 0;
    [lengthData getBytes:&getDataLength1 length:8];

将data转成NSInteger获取到data的实际长度

使用场景一:socket通信粘包处理
当读取到数据写入,先将数据加入到缓冲区

self.dataBuffer = [NSMutableData data];
[self.dataBuffer appendData:readData];

此处的readData为数据流读出的某个完整数据的一部分,appendData:readData这个代码可能执行多次
截取前4个字节(这个字节数不一定要4个字节 ,完全可以自己定义,跟服务器约定好就可以)

    NSInteger dataLength = 0;
    [self.dataBuffer getBytes:&getDataLength1 length:8];
    if (self.dataBuffer.length >= dataLength+4) {
          //取出我们想要的数据
          NSData *completeData = [self.dataBuffer subdataWithRange:NSMakeRange(4, dataLength)];
          //然后处理取出来的数据
          //略.........
          //移除已经拆包的数据
          [self.dataBuffer setData:[self.dataBuffer subdataWithRange:NSMakeRange(4+dataLength, self.dataBuffer.length - 4 - dataLength)]];
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容