美文网首页
GCDAsyncSocket粘包,断包简单处理

GCDAsyncSocket粘包,断包简单处理

作者: adrian920 | 来源:发表于2018-09-20 11:27 被阅读70次

    最近做了个APP,在APP中用GCDAsyncSocket与服务器建立TCP长连接,并通过服务器控制一个设备。这个过程中,服务器会返回一些数据,有时候数据量大,接收数据时会出现断包的问题。第一次做长连接,解析数据时顾头不顾尾,只注意到本次数据的完整性,解析完后直接丢掉数据,下次的数据的包头就可能就被掐掉了,导致解析的数据长度出错,进而根据长度取数据越界而crash。

    下面粘贴下自己的解决方法。

    接收数据是在这个代理方法中:

    - (void)socket:(GCDAsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag {

        [self.receiveData appendData:data]; // receiveData是NSMutableData类型,作为一个数据缓冲池,每次从开始位置(0)取想要的数据

        NSUInteger length = [self getLength:self.receiveData];// 根据你自定义的协议解析数据长度

        if(self.completeData.length >=  length) {

                NSData*valideData = [self getValideDataWithLength:length];// 本次应该接收的数据,你可以解析它了

            }

        }

        [self pullTheMsg];// 继续接收数据

    }

    // 根据长度取出本次应该接收的数据并返回,然后在缓冲数据中清除本次数据,后面的数据前移,保证每次从0位置开始取数据。

    - (NSData*)getValideDataWithLength:(NSUInteger)length{

        NSData*valideData = [self.receiveData subdataWithRange:NSMakeRange(0, length)];

        // 余下的数据前移,一时没找到好方法,用了个笨的

        NSData*lastData = [self.receiveData subdataWithRange:NSMakeRange(length,self.receiveData.length- length)];

        [self clearReceiveData];

        [self.receiveData appendData:lastData];

        return valideData;

    }

    // 清空所有缓冲数据

    - (void)clearReceiveData{

        [self.receiveData resetBytesInRange:NSMakeRange(0, [self.receiveData length])];

        [self.receiveData setLength:0];

    }

    相关文章

      网友评论

          本文标题:GCDAsyncSocket粘包,断包简单处理

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