GCDAsyncSocket解决粘包问题
发送端
数据源头部添加文字总数
- (void)sendMessage:(NSString *)message{
NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
data = [self addTotalLengthToData:data];
[socket writeData:data withTimeout:-1 tag:0];
[socket readDataWithTimeout:-1 tag:0];
}
- (NSData *)addTotalLengthToData:(NSData *)data{
NSMutableData *sendData = [NSMutableData data];
// 获取数据长度
NSInteger datalength = data.length;
// NSInteger长度转 NSData
NSData *lengthData = [NSData dataWithBytes:&datalength length:sizeof(datalength)];
// 长度几个字节和服务器协商好。这里我们用的是4个字节存储长度信息
NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0,4)];
// 拼接长度信息
[sendData appendData:newLengthData];
//拼接数据
[sendData appendData:data];
return sendData;
}
接收端
- (void)socket:(GCDAsyncSocket*)sockdidReadData:(NSData*)datawithTag:(long)tag{
[_locklock];
NSMutableData *readBuf = self.clientReadBuf;
[self LYHandleDidReadData:data socket:sock readBuf:readBuf];
[_lockunlock];
}
- (void)LYHandleDidReadData:(NSData*)data socket:(GCDAsyncSocket*)sock readBuf:(NSMutableData*)readBuf{
//将数据存入缓存区
[readBuf appendData:data];
NSMutableArray *saveCompleteDataArray = [NSMutableArray array];
// 如果长度大于4个字节,表示有数据包。4字节为包头,存储包内数据长度
while(readBuf.length>=4) {
NSInteger datalength =0;
// 获取包头,并获取长度
[[readBuf subdataWithRange:NSMakeRange(0,4)]getBytes:&datalength length:sizeof(datalength)];
// 判断缓存区内是否有包
if(readBuf.length>= (datalength+4)) {
// 获取去掉包头的数据
NSData*realData = [[readBuf subdataWithRange:NSMakeRange(4, datalength)] copy];
// 解析处理
[saveCompleteDataArray addObject:realData];
// 移除已经拆过的包
readBuf = [NSMutableData dataWithData:[readBuf subdataWithRange:NSMakeRange(datalength+4, readBuf.length- (datalength+4))]];
}else{
break;
}
}
self.clientReadBuf= readBuf;
//查看有多少包 saveCompleteDataArray为解析的数据
NSLog(@"saveCompleteDataArray.count---%ld", saveCompleteDataArray.count);
[sock readDataWithTimeout:-1 tag:0];
}