/**
tcp通信必然伴随着粘包或者拆包的情况.而每次通过didReadData这个委托方法收到的是数据都是以包为单位.拆包粘包说白了就是服务器一次给你发了很多条信息,但是这些信息不是一条信息一个包,而是一条信息分了几个包发来,或者几条信息的数据合到一个包发来了.
java貌似自己有框架,闭着眼就能完成拆包合包的工作.但是oc上貌似没找到.只好手动.那首先要跟服务器有个协议,说明一下以什么作为一条信息的节点.比如我们,每条信息的头四个字节是用来保存这条信息的应有长度的.接到信息首先要读取长度,然后再跟收到的数据包长度对比.如果收到的长度刚刚好,说明这是一条完整的信息,直接封起来就行.如果收到的长度比预计长度短,说明信息被拆包发送,那就要继续跟下一个包进行拼装,再检验长度.如果收到的长度比预计的长,说明发生了粘包,那就要根据预计长度对数据包的数据进行拆分,对拆出的两部分数据继续进行处理.
* 处理_bufferData * 主要处理拆包粘包问题.获得每段数据的长度之后,和当前buffer比较,如果刚好说明接收完全;如果buffer过大说明服务端粘包,需要拆包;如果buffer小说明服务端拆包,需要合包 * * @param newData 获取的新数据,如果只是本地拆包则传nil */ - (void)handleBufferData:(NSData *)newData { if (newData) { //这是一个缓冲区,因为是全局的,并且是单例中,所以在数据取走的时候一定要清空 [_bufferData appendData:newData]; } //首先取前四位 int i = 0; [_bufferData getBytes:&i range:NSMakeRange(0, 4)]; //因为oc和java字节数组的高地位顺序是反的,所以要翻转一下顺序 Byte *fix = [self overturnIntByteArr:i]; memcpy(&i, fix, 4); free(fix); //刚好 if (i == [_bufferData length]-4) { NSData *contentData = [_bufferData subdataWithRange:NSMakeRange(4, i)]; //完整接收了一条信息的处理 [self finishGetWholeData:contentData]; _bufferData = [NSMutableData data]; } //需要拆包 else if (i < [_bufferData length]-4) { NSData *contentData = [_bufferData subdataWithRange:NSMakeRange(4, i)]; //这是完成了第一个包的数据的接收 [self finishGetWholeData:contentData]; NSData *buffer = [_bufferData subdataWithRange:NSMakeRange(i+4, _bufferData.length-i-4)]; _bufferData = [NSMutableData data]; [_bufferData appendData:buffer]; //继续进行判断处理 [self handleBufferData:nil]; } }
浙公网安备 33010602011771号