GCDAsyncSocket粘包,断包简单处理

2018-09-20  本文已影响70人  adrian920

最近做了个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];

}

上一篇下一篇

猜你喜欢

热点阅读