数据包格式.png在tcp连接中 难免会出现粘包和断包的现象,这样我们就无法获取到正确的信息,所以在开发过程中我们要对数据粘包和断包进行处理,拿到我们想要的数据
示例:FC 000C 0001 112233445566 01 0010 FF 94
假如这就是我们想要拿到的正确数据
LEN0和LEN1是数据长度
首先我们要先打拿到整个数据的长度 000C是一个16进制数,转换成十进制就是12。
这里的12指的是数据本身的长度,不是转换成字符串的长度,字符串的长度是24。
所以内容数据就是 0001 112233445566 01 0010 FF
最后的94是校验码
所以我们需要根据内容数据的长度12去拿取正确的数据
代码如下
//存储TCP连接接收的数据 用于解决粘包、断包问题
@property (strong, nonatomic) NSMutableData *readBuf;
在接收到数据方法里进行处理
FC 000C 0001 112233445566 01 0010 FF 94
//处理粘包与断包
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
_readBuf = [NSMutableData dataWithData:data];
// NSLog(@"直接得到的数据%@",_readBuf);
while (_readBuf.length >= 3) {
//长度数据 000C
NSData *lengthData = [_readBuf subdataWithRange:NSMakeRange(1, 2)];
//内容长度 12
NSInteger length = [[self toHexstring:[self dataToString:lengthData]] integerValue];
//一个包的完整长度 加上开头的FC000C和最后的校验码94
NSInteger complateDataLength = length + 4;
if (_readBuf.length >= complateDataLength) {//够一个整包长度
//截取一个包的长度(解决粘包)
NSData *complateData = [_readBuf subdataWithRange:NSMakeRange(0, complateDataLength)];
//处理数据
[self handleTcpResponseData:complateData];
//从缓存中截掉处理完的数据,继续循环
_readBuf = [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(complateDataLength, _readBuf.length - complateDataLength)]];
} else {//如果缓存中的数据长度不够一个包的长度,则包不完整(处理半包,继续读取)
[sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据
return;
}
//缓存中数据都处理完了,继续读取新数据
[sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据
}
}
handleTcpResponseData方法是自己写的处理数据方法。
网友评论