CocoaAsyncSocket + Protobuf 处理粘包和拆包问题

      在上一篇文章《iOS之ProtocolBuffer搭建和示例demo》分享环境的搭建, 我们和服务器进行IM通讯用了github有名的框架CocoaAsynSocket, 然后和服务器之间的数据媒介是ProtoBuf。然后后面在开发的过程中也碰到了拆包和粘包问题,这方面网上资料很少,曲折了一下才解决,这里分享一下问题的解决过程!

  首先描述下碰到的问题:

  1、服务器发送内容很长的数据过来的时候,GCDAsyncSocket监听收到的一个包解析不了,一直要接收好几个包拼接才是这条数据的完整包,即所谓的拆包/断包;

  2、服务器快速发送多条数据过来,传到客户端这边的时候几条数据合成了一个包,即所谓的粘包。所以想解析这些粘在一起的数据,必须知道每条数据的长度,才能正确切割解析。

  先上关键代码,解决读取每条数据的头部字节,根据头部字节读取这条数据的内容长度。这样才能完美的解决粘包问题。由于根据数据的长度不一样,导致头部字节占用的长度也会不一样,比如说我这里反复测试的结果头部占用字节一般为1和2,短内容数据头部占用字节长度为1,长内容数据头部占用字节长度为2。这里的代码参考了谷歌提供的Protobuf的objectivec版的源码。

/** 关键代码:获取data数据的内容长度和头部长度: index --> 头部占用长度 (头部占用长度1-4个字节) */
- (int32_t)getContentLength:(NSData *)data withHeadLength:(int32_t *)index{
    
    int8_t tmp = [self readRawByte:data headIndex:index];
    
    if (tmp >= 0) return tmp;
    
    int32_t result = tmp & 0x7f;
    if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
        result |= tmp << 7;
    } else {
        result |= (tmp & 0x7f) << 7;
        if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
            result |= tmp << 14;
        } else {
            result |= (tmp & 0x7f) << 14;
            if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
                result |= tmp << 21;
            } else {
                result |= (tmp & 0x7f) << 21;
                result |= (tmp = [self readRawByte:data headIndex:index]) << 28;
                if (tmp < 0) {
                    for (int i = 0; i < 5; i++) {
                        if ([self readRawByte:data headIndex:index] >= 0) {
                            return result;
                        }
                    }
                    
                    result = -1;
                }
            }
        }
    }
    return result;
}

/** 读取字节 */
- (int8_t)readRawByte:(NSData *)data headIndex:(int32_t *)index{
    
    if (*index >= data.length) return -1;
    
    *index = *index + 1;
    
    return ((int8_t *)data.bytes)[*index - 1];
}

解决了读取每条数据的头部占用字节,和内容的长度,粘包问题就好解决了。

再上比较完整的代码:从客户端监听服务器发送过来的数据到处理拆包和粘包问题,然后解析成自定义的protobuf模型类。

/** 监听来自服务器的消息代理方法 */
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    [self.receiveData appendData:data];
    
    //读取data的头部占用字节 和 从头部读取内容长度
    //验证结果:数据比较小时头部占用字节为1,数据比较大时头部占用字节为2
    int32_t headL = 0;
    int32_t contentL = [self getContentLength:self.receiveData withHeadLength:&headL];
    
    if (contentL < 1){
        [sock readDataWithTimeout:-1 tag:0];
        return;
    }
    
    //拆包情况下:继续接收下一条消息,直至接收完这条消息所有的拆包,再解析
    if (headL + contentL > self.receiveData.length){
        [sock readDataWithTimeout:-1 tag:0];
        return;
    }
    
    //当receiveData长度不小于第一条消息内容长度时,开始解析receiveData
    [self parseContentDataWithHeadLength:headL withContentLength:contentL];
    [sock readDataWithTimeout:-1 tag:tag];
} 

#pragma mark - private methods  辅助方法
/** 解析二进制数据:NSData --> 自定义模型对象 */
- (void)parseContentDataWithHeadLength:(int32_t)headL withContentLength:(int32_t)contentL{
    
    NSRange range = NSMakeRange(0, headL + contentL);   //本次解析data的范围
    NSData *data = [self.receiveData subdataWithRange:range]; //本次解析的data
    
    GPBCodedInputStream *inputStream = [GPBCodedInputStream streamWithData:data];
    
    NSError *error;
    ChatMsg *obj = [ChatMsg parseDelimitedFromCodedInputStream:inputStream extensionRegistry:nil error:&error];
    
    if (!error){
        if (obj) [self saveReceiveInfo:obj];  //保存解析正确的模型对象
        [self.receiveData replaceBytesInRange:range withBytes:NULL length:0];  //移除已经解析过的data
    }
    
    if (self.receiveData.length < 1) return;
    
    //对于粘包情况下被合并的多条消息,循环递归直至解析完所有消息
    headL = 0;
    contentL = [self getContentLength:self.receiveData withHeadLength:&headL];
    if (headL + contentL > self.receiveData.length) return; //实际包不足解析,继续接收下一个包

    [self parseContentDataWithHeadLength:headL withContentLength:contentL]; //继续解析下一条
}

/** 获取data数据的内容长度和头部长度: index --> 头部占用长度 (头部占用长度1-4个字节) */
- (int32_t)getContentLength:(NSData *)data withHeadLength:(int32_t *)index{
    
    int8_t tmp = [self readRawByte:data headIndex:index];
    
    if (tmp >= 0) return tmp;
    
    int32_t result = tmp & 0x7f;
    if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
        result |= tmp << 7;
    } else {
        result |= (tmp & 0x7f) << 7;
        if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
            result |= tmp << 14;
        } else {
            result |= (tmp & 0x7f) << 14;
            if ((tmp = [self readRawByte:data headIndex:index]) >= 0) {
                result |= tmp << 21;
            } else {
                result |= (tmp & 0x7f) << 21;
                result |= (tmp = [self readRawByte:data headIndex:index]) << 28;
                if (tmp < 0) {
                    for (int i = 0; i < 5; i++) {
                        if ([self readRawByte:data headIndex:index] >= 0) {
                            return result;
                        }
                    }
                    
                    result = -1;
                }
            }
        }
    }
    return result;
}

/** 读取字节 */
- (int8_t)readRawByte:(NSData *)data headIndex:(int32_t *)index{
    
    if (*index >= data.length) return -1;
    
    *index = *index + 1;
    
    return ((int8_t *)data.bytes)[*index - 1];
}

/** 处理解析出来的信息 */
- (void)saveReceiveInfo:(ChatMsg *)obj{
    //...
}

--------------------- print log test start --------------------- 

在GCDAsyncSocket监听服务器代理方法里面打印日志,查看下正常包、粘包、拆包的日志信息:

1、正常包的打印日志(服务器发送一条消息达到客户端只有一个包: 1 + 49 = 50  ):

实际接收总包长度:50, 当前接收包长度:50, 读取头部占用长度: 1, 读取内容长度:49, 当前包字节:
<3108c901 122c0a0a 74363330 32303137 30361203 43636318 01220c64 656e6773 6f6e676e 616e782a 00300038 9af6ccd5 b72b>

2、粘包情况下的日志 (发送的4条消息合到了一个包里:(1 + 49) * 4 = 200  ):

实际接收总包长度:200, 当前接收包长度:200, 读取头部占用长度: 1, 读取内容长度:49, 当前包字节:
<3108c901 122c0a0a 74363330 32303137 30361203 46666618 01220c64 656e6773 6f6e676e 616e782a 00300038 f2cfccd5 b72b3108 c901122c 0a0a7436 33303230 31373036 12034767 67180122 0c64656e 67736f6e 676e616e 782a0030 003898d0 ccd5b72b 3108c901 122c0a0a 74363330 32303137 30361203 5a7a7a18 01220c64 656e6773 6f6e676e 616e782a 00300038 add0ccd5 b72b3108 c901122c 0a0a7436 33303230 31373036 12035878 78180122 0c64656e 67736f6e 676e616e 782a0030 0038c1d0 ccd5b72b>

3、拆包情况下的日志 (发送一条内容较长的消息,最后到达客户端时被拆成了三个接收包: 4200 + 1400 + 292 =  2+5890 ):

实际接收总包长度:4200, 当前接收包长度:4200, 读取头部占用长度: 2, 读取内容长度:5890, 当前包字节:
<822e08c9 0112fc2d 0a0a7436 33303230 31373036 12d22d50 e7acace4 b880e6ac a16f6e65 6f6e656f 6e65206f 6e656f6e 656f6d65 20e68891 e78eb0e5 9ca8e79c 9fe79a84 e99d9ee5 b8b8e684 9fe8b0a2 e68891e8 bf87e58e bbe79a84 e58aaae5 8a9befbc 8ce8a681 e698afe8 8bb1e8af ade4b88d e5a5bdef bc8ce688 91e58faf e883bde9 83bde581 9ae79a84 e697b6e5 8099efbc 8ce4b88d e8a18c7e 7e0a0ae8 bf99e5b0 b1e698af e4b88de6 8782e5be 97e4b893 efbc8ce6 b2a1e4bb 80e4b988 e68bbfe5 be97e587 bae6898b e79a84e6 a188e4be 8befbc8c e5ada6e4 bc9ae59c a8e4b880 e4b8aae9 a286e59f 9fe68a8a e4bb96e5 819ae588 b0e4bc98 e7a780ef bc8ce99d 9ee5b8b8 e79a84e5 85b3e994 aee38082 0a0ae4bd 86e698af e5be88e5 8fafe683 9cefbc8c e8bf99e4 b8aae7a4 bee4bc9a e69c89e5 be88e5a4 9ae599aa e99fb3ef bc8ce697 b6e4b88d e697b6e7 9a84e4b8 80e79bb4 e59ca8e5 b9b2e689 b0e79d80 e4bda07e 7e20e58c 85e68bac e68891e4 b99fe698 afe5958a efbc8ce6 8891e6af 8fe5a4a9 e68ea5e6 94b6e79a 84e4bfa1 e681afe5 a49fe5a4 9ae4ba86 e590a7ef bc8ce590 84e4b8aa e696b9e9 9da2e79a 84e4baba efbc8ce8 b584e6ba 90e280a6 2e2ee79c 9fe698af e69c89e5 be88e5a4 9ae69cba e4bc9aef bc8ce5be 88e5a49a e5a5bde9 a1b9e79b aeefbc8c e4bda0e8 afb4e5bf 83e58aa8 e4b88def bc9fe4bd a0e8afb4 e683b3e8 a681e4b8 8defbc9f 0a0ae5bd 93e784b6 7e7e0a0a e58fafe6 98afefbc 8ce5a682 e69e9ce6 8891e4bb 80e4b988 e983bde5 819aefbc 8ce69c80 e5908e50 e7acace4 b880e6ac a16f6e65 6f6e656f 6e65206f 6e656f6e 656f6d65 20e68891 e78eb0e5 9ca8e79c 9fe79a84 e99d9ee5 b8b8e684 9fe8b0a2 e68891e8 bf87e58e bbe79a84 e58aaae5 8a9befbc 8ce8a681 e698afe8 8bb1e8af ade4b88d e5a5bdef bc8ce688 91e58faf e883bde9 83bde581 9ae79a84 e697b6e5 8099efbc 8ce4b88d e8a18c7e 7e0a0ae8 bf99e5b0 b1e698af e4b88de6 8782e5be 97e4b893 efbc8ce6 b2a1e4bb 80e4b988 e68bbfe5 be97e587 bae6898b e79a84e6 a188e4be 8befbc8c e5ada6e4 bc9ae59c a8e4b880 e4b8aae9 a286e59f 9fe68a8a e4bb96e5 819ae588 b0e4bc98 e7a780ef bc8ce99d 9ee5b8b8 e79a8450 e7acace4 b880e6ac a16f6e65 6f6e656f 6e65206f 6e656f6e 656f6d65 20e68891 e78eb0e5 9ca8e79c 9fe79a84 e99d9ee5 b8b8e684 9fe8b0a2 e68891e8 bf87e58e bbe79a84 e58aaae5 8a9befbc 8ce8a681 e698afe8 8bb1e8af ade4b88d e5a5bdef bc8ce688 91e58faf e883bde9 83bde581 9ae79a84 e697b6e5 8099efbc 8ce4b88d e8a18c7e 7e0a0ae8 bf99e5b0 b1e698af e4b88de6 8782e5be 97e4b893 efbc8ce6 b2a1e4bb 80e4b988 e68bbfe5 be97e587 bae6898b e79a84e6 a188e4be 8befbc8c e5ada6e4 bc9ae59c a8e4b880 e4b8aae9 a286e59f 9fe68a8a e4bb96e5 819ae588 b0e4bc98 e7a780ef bc8ce99d 9ee5b8b8 e79a84e5 85b3e994 aee38082 0a0ae4bd 86e698af e5be88e5 8fafe683 9cefbc8c e8bf99e4 b8aae7a4 bee4bc9a e69c89e5 be88e5a4 9ae599aa e99fb3ef bc8ce697 b6e4b88d e697b6e7 9a84e4b8 80e79bb4 e59ca8e5 b9b2e689 b0e79d80 e4bda07e 7e20e58c 85e68bac e68891e4 b99fe698 afe5958a efbc8ce6 8891e6af 8fe5a4a9 e68ea5e6 94b6e79a 84e4bfa1 e681afe5 a49fe5a4 9ae4ba86 e590a7ef bc8ce590 84e4b8aa e696b9e9 9da2e79a 84e4baba efbc8ce8 b584e6ba 90e280a6 2e2ee79c 9fe698af e69c89e5 be88e5a4 9ae69cba e4bc9aef bc8ce5be 88e5a49a e5a5bde9 a1b9e79b aeefbc8c e4bda0e8 afb4e5bf 83e58aa8 e4b88def bc9fe4bd a0e8afb4 e683b3e8 a681e4b8 8defbc9f 0a0ae5bd 93e784b6 7e7e0a0a e58fafe6 98afefbc 8ce5a682 e69e9ce6 8891e4bb 80e4b988 e983bde5 819aefbc 8ce69c80 e5908e50 e7acace4 b880e6ac a16f6e65 6f6e656f 6e65206f 6e656f6e 656f6d65 20e68891 e78eb0e5 9ca8e79c 9fe79a84 e99d9ee5 b8b8e684 9fe8b0a2 e68891e8 bf87e58e bbe79a84 e58aaae5 8a9befbc 8ce8a681 e698afe8 8bb1e8af ade4b88d e5a5bdef bc8ce688 91e58faf e883bde9 83bde581 9ae79a84 e697b6e5 8099efbc 8ce4b88d e8a18c7e 7e0a0ae8 bf99e5b0 b1e698af e4b88de6 8782e5be 97e4b893 efbc8ce6 b2a1e4bb 80e4b988 e68bbfe5 be97e587 bae6898b e79a84e6 a188e4be 8befbc8c e5ada6e4 bc9ae59c a8e4b880 e4b8aae9 a286e59f 9fe68a8a e4bb96e5 819ae588 b0e4bc98 e7a780ef bc8ce99d 9ee5b8b8 e79a84e5 85b3e994 aee38082 0a0ae4bd 86e698af e5be88e5 8fafe683 9cefbc8c e8bf99e4 b8aae7a4 bee4bc9a e69c89e5 be88e5a4 9ae599aa e99fb3ef bc8ce697 b6e4b88d e697b6e7 9a84e4b8 80e79bb4 e59ca8e5 b9b2e689 b0e79d80 e4bda07e 7e20e58c 85e68bac e68891e4 b99fe698 afe5958a efbc8ce6 8891e6af 8fe5a4a9 e68ea5e6 94b6e79a 84e4bfa1 e681afe5 a49fe5a4 9ae4ba86 e590a7ef bc8ce590 84e4b8aa e696b9e9 9da2e79a 84e4baba efbc8ce8 b584e6ba 90e280a6 2e2ee79c 9fe698af e69c89e5 be88e5a4 9ae69cba e4bc9aef bc8ce5be 88e5a49a e5a5bde9 a1b9e79b aeefbc8c e4bda0e8 afb4e5bf 83e58aa8 e4b88def bc9fe4bd a0e8afb4 e683b3e8 a681e4b8 8defbc9f 0a0ae5bd 93e784b6 7e7e0a0a e58fafe6 98afefbc 8ce5a682 e69e9ce6 8891e4bb 80e4b988 e983bde5 819aefbc 8ce69c80 e5908ee6 8891e882 afe5ae9a e593aae4 b880e6a0 b7e983bd e5819ae4 b88de5a5 bde38082 e59084e4 bd8defbc 8ce4bda0 e4bbace4 b880e5ae 9ae8a681 e79fa5e9 8193e887 aae5b7b1 e683b3e8 a681e4bb 80e4b988 efbc810a 0a0a0ae5 a4a7e5ad a6e982a3 e4bc9ae5 84bfefbc 8ce8b791 e6ada5ef bc8ce8af bbe4b9a6 efbc8ce9 94bbe782 bce68891 e5b0b1e5 b7b2e7bb 8fe99d9e e5b8b8e6 b885e6a5 9ae68891 e683b3e8 a681e79a 84e698af e4bb80e4 b988e6a0 b7e79a84 e8b7afef bc8ce99c 80e8a681 e9809ae8 bf87e4bb 80e4b988 e6a0b7e7 9a84e58a aae58a9b e58ebbe5 88b0e8be bee38082 e588b0e4 bb8ae5a4 a9e69bb4 e698afe5 a682e6ad a4efbc8c e5a5bde7 9a84e4ba bae7949f e79a84e5 a49ae6b2 a10ae4bd 86e4bda0 e4bbace4 b88de79f a5e98193 efbc8ce6 9c89e697 b6e58099 e79c9fe7 9a84e8a7 89e5be97 efbc8ce4 b880e69d afe88cb6 efbc8ce7 84b6e590 8ee4b880 e9a696e5 969ce6ac a2e79a84 50e7acac e4b880e6 aca16f6e 656f6e65 6f6e6520 6f6e656f 6e656f6d 6520e688 91e78eb0 e59ca8e7 9c9fe79a 84e99d9e e5b8b8e6 849fe8b0 a2e68891 e8bf87e5 8ebbe79a 84e58aaa e58a9bef bc8ce8a6 81e698af e88bb1e8 afade4b8 8de5a5bd efbc8ce6 8891e58f afe883bd e983bde5 819ae79a 84e697b6 e58099ef bc8ce4b8 8de8a18c 7e7e0a0a e8bf99e5 b0b1e698 afe4b88d e68782e5 be97e4b8 93efbc8c e6b2a1e4 bb80e4b9 88e68bbf e5be97e5 87bae689 8be79a84 e6a188e4 be8befbc 8ce5ada6 e4bc9ae5 9ca8e4b8 80e4b8aa e9a286e5 9f9fe68a 8ae4bb96 e5819ae5 88b0e4bc 98e7a780 efbc8ce9 9d9ee5b8 b8e79a84 e585b3e9 94aee380 820a0ae4 bd86e698 afe5be88 e58fafe6 839cefbc 8ce8bf99 e4b8aae7 a4bee4bc 9ae69c89 e5be88e5 a49ae599 aae99fb3 efbc8ce6 97b6e4b8 8de697b6 e79a84e4 b880e79b b4e59ca8 e5b9b2e6 89b0e79d 80e4bda0 7e7e20e5 8c85e68b ace68891 e4b99fe6 98afe595 8aefbc8c e68891e6 af8fe5a4 a9e68ea5 e694b6e7 9a84e4bf a1e681af e5a49fe5 a49ae4ba 86e590a7 efbc8ce5 9084e4b8 aae696b9 e99da2e7 9a84e4ba baefbc8c e8b584e6 ba90e280 a62e2ee7 9c9fe698 afe69c89 e5be88e5 a49ae69c bae4bc9a efbc8ce5 be88e5a4 9ae5a5bd e9a1b9e7 9baeefbc 8ce4bda0 e8afb4e5 bf83e58a a8e4b88d efbc9fe4 bda0e8af b4e683b3 e8a681e4 b88defbc 9f0a0ae5 bd93e784 b67e7e0a 0ae58faf e698afef bc8ce5a6 82e69e9c e68891e4 bb80e4b9 88e983bd e5819aef bc8ce69c 80e5908e e68891e8 82afe5ae 9ae593aa e4b880e6 a0b7e983 bde5819a e4b88de5 a5bde380 82e59084 e4bd8def bc8ce4bd a0e4bbac e4b880e5 ae9ae8a6 81e79fa5 e98193e8 87aae5b7 b1e683b3 e8a681e4 bb80e4b9 88efbc81 0a0a0a0a e5a4a7e5 ada6e982 a3e4bc9a e584bfef bc8ce8b7 91e6ada5 efbc8ce8 afbbe4b9 a6efbc8c e994bbe7 82bce688 91e5b0b1 e5b7b2e7 bb8fe99d 9ee5b8b8 e6b885e6 a59ae688 91e683b3 e8a681e7 9a84e698 afe4bb80 e4b988e6 a0b7e79a 84e8b7af efbc8ce9 9c80e8a6 81e9809a e8bf87e4 bb80e4b9 88e6a0b7 e79a84e5 8aaae58a 9be58ebb e588b0e8 bebee380 82e588b0 e4bb8ae5 a4a9e69b b4e698af e5a682e6 ada4efbc 8ce5a5bd e79a84e4 babae794 9fe79a84 e5a49ae6 b2a10ae4 bd86e4bd a0e4bbac e4b88de7 9fa5e981 93efbc8c e69c89e6 97b6e580 99e79c9f e79a84e8 a789e5be 97efbc8c e4b880e6 9dafe88c b6efbc8c e784b6e5 908ee4b8 80e9a696 e5969ce6 aca2e79a 84e6ad8c efbc8ce5 b0b1e883 bde6bba1 e8b6b3e6 8980e69c 89e38082 e7acace4 ba8ce6ac a1e7bb93 e69d9fef bc81efbc 81efbc81 656e6465 6e647477 6f20e6ad 8cefbc8c e5b0b1e8 83bde6bb a1e8b6b3 e68980e6 9c89e380 82e7acac e4ba8ce6 aca1e7bb 93e69d9f efbc81ef bc81efbc 81656e64 656e6474 776f20e6 8891e882 afe5ae9a e593aae4 b880e6a0 b7e983bd e5819ae4 b88de5a5 bde38082 e59084e4 bd8defbc 8ce4bda0 e4bbace4 b880e5ae 9ae8a681 e79fa5e9 8193e887 aae5b7b1 e683b3e8 a681e4bb 80e4b988 efbc810a 0a0a0ae5 a4a7e5ad a6e982a3 e4bc9ae5 84bfefbc 8ce8b791 e6ada5ef bc8ce8af bbe4b9a6 efbc8ce9 94bbe782 bce68891 e5b0b1e5 b7b2e7bb 8fe99d9e e5b8b8e6 b885e6a5 9ae68891 e683b3e8 a681e79a 84e698af e4bb80e4 b988e6a0 b7e79a84 e8b7afef bc8ce99c 80e8a681 e9809ae8 bf87e4bb 80e4b988 e6a0b7e7 9a84e58a aae58a9b e58ebbe5 88b0e8be bee38082 e588b0e4 bb8ae5a4 a9e69bb4 e698afe5 a682e6ad a4efbc8c e5a5bde7 9a84e4ba bae7949f e79a84e5 a49ae6b2 a10ae4bd 86e4bda0 e4bbace4 b88de79f a5e98193 efbc8ce6 9c89e697 b6e58099 e79c9fe7 9a84e8a7 89e5be97 efbc8ce4 b880e69d afe88cb6 efbc8ce7 84b6e590 8ee4b880 e9a696e5 969ce6ac a2e79a84 e6ad8cef bc8ce5b0 b1e883bd e6bba1e8 b6b3e689 80e69c89 e38082e7 acace4ba 8ce6aca1 e7bb93e6 9d9fefbc 81efbc81 efbc8165 6e64656e 6474776f e585b3e9 94aee380 820a0ae4 bd86e698 afe5be88 e58fafe6 839cefbc 8ce8bf99 e4b8aae7 a4bee4bc 9ae69c89 e5be88e5 a49ae599 aae99fb3 efbc8ce6 97b6e4b8 8de697b6 e79a84e4 b880e79b b4e59ca8 e5b9b2e6 89b0e79d 80e4bda0 7e7e20e5 8c85e68b ace68891 e4b99fe6 98afe595 8aefbc8c e68891e6 af8fe5a4 a9e68ea5 e694b6e7 9a84e4bf a1e681af e5a49fe5 a49ae4ba 86e590a7 efbc8ce5 9084e4b8 aae696b9 e99da2e7 9a84e4ba baefbc8c e8b584e6 ba90e280 a62e2ee7 9c9fe698 afe69c89 e5be88e5 a49ae69c bae4bc9a efbc8ce5 be88e5a4 9ae5a5bd e9a1b9e7 9baeefbc 8ce4bda0 e8afb4e5 bf83e58a a8e4b88d efbc9fe4 bda0e8af b4e683b3 e8a681e4 b88defbc 9f0a0ae5 bd93e784 b67e7e0a 0ae58faf e698afef bc8ce5a6 82e69e9c e68891e4 bb80e4b9 88e983bd e5819aef bc8ce69c 80e5908e e68891e8 82afe5ae 9ae593aa e4b880e6 a0b7e983 bde5819a e4b88de5 a5bde380 82e59084 e4bd8def bc8ce4bd a0e4bbac e4b880e5 ae9ae8a6 81e79fa5 e98193e8 87aae5b7 b1e683b3 e8a681e4 bb80e4b9 88efbc81 0a0a0a0a e5a4a7e5 ada6e982 a3e4bc9a e584bfef bc8ce8b7 91e6ada5 efbc8ce8 afbbe4b9 a6efbc8c e994bbe7 82bce688 91e5b0b1>



实际接收总包长度:5600, 当前接收包长度:1400, 读取头部占用长度: 2, 读取内容长度:5890, 当前包字节:
<e5b7b2e7 bb8fe99d 9ee5b8b8 e6b885e6 a59ae688 91e683b3 e8a681e7 9a84e698 afe4bb80 e4b988e6 a0b7e79a 84e8b7af efbc8ce9 9c80e8a6 81e9809a e8bf87e4 bb80e4b9 88e6a0b7 e79a84e5 8aaae58a 9be58ebb e588b0e8 bebee380 82e588b0 e4bb8ae5 a4a9e69b b4e698af e5a682e6 ada4efbc 8ce5a5bd e79a84e4 babae794 9fe79a84 e5a49ae6 b2a10ae4 bd86e4bd a0e4bbac e4b88de7 9fa5e981 93efbc8c e69c89e6 97b6e580 99e79c9f e79a84e8 a789e5be 97efbc8c e4b880e6 9dafe88c b6efbc8c e784b6e5 908ee4b8 80e9a696 e5969ce6 aca2e79a 8450e7ac ace4b880 e6aca16f 6e656f6e 656f6e65 206f6e65 6f6e656f 6d6520e6 8891e78e b0e59ca8 e79c9fe7 9a84e99d 9ee5b8b8 e6849fe8 b0a2e688 91e8bf87 e58ebbe7 9a84e58a aae58a9b efbc8ce8 a681e698 afe88bb1 e8afade4 b88de5a5 bdefbc8c e68891e5 8fafe883 bde983bd e5819ae7 9a84e697 b6e58099 efbc8ce4 b88de8a1 8c7e7e0a 0ae8bf99 e5b0b1e6 98afe4b8 8de68782 e5be97e4 b893efbc 8ce6b2a1 e4bb80e4 b988e68b bfe5be97 e587bae6 898be79a 84e6a188 e4be8bef bc8ce5ad a6e4bc9a e59ca8e4 b880e4b8 aae9a286 e59f9fe6 8a8ae4bb 96e5819a e588b0e4 bc98e7a7 80efbc8c e99d9ee5 b8b8e79a 84e585b3 e994aee3 80820a0a e4bd86e6 98afe5be 88e58faf e6839cef bc8ce8bf 99e4b8aa e7a4bee4 bc9ae69c 89e5be88 e5a49ae5 99aae99f b3efbc8c e697b6e4 b88de697 b6e79a84 e4b880e7 9bb4e59c a8e5b9b2 e689b0e7 9d80e4bd a07e7e20 e58c85e6 8bace688 91e4b99f e698afe5 958aefbc 8ce68891 e6af8fe5 a4a9e68e a5e694b6 e79a84e4 bfa1e681 afe5a49f e5a49ae4 ba86e590 a7efbc8c e59084e4 b8aae696 b9e99da2 e79a84e4 babaefbc 8ce8b584 e6ba90e2 80a62e2e e79c9fe6 98afe69c 89e5be88 e5a49ae6 9cbae4bc 9aefbc8c e5be88e5 a49ae5a5 bde9a1b9 e79baeef bc8ce4bd a0e8afb4 e5bf83e5 8aa8e4b8 8defbc9f e4bda0e8 afb4e683 b3e8a681 e4b88def bc9f0a0a e5bd93e7 84b67e7e 0a0ae58f afe698af efbc8ce5 a682e69e 9ce68891 e4bb80e4 b988e983 bde5819a efbc8ce6 9c80e590 8ee68891 e882afe5 ae9ae593 aae4b880 e6a0b7e9 83bde581 9ae4b88d e5a5bde3 8082e590 84e4bd8d efbc8ce4 bda0e4bb ace4b880 e5ae9ae8 a681e79f a5e98193 e887aae5 b7b1e683 b3e8a681 e4bb80e4 b988efbc 810a0a0a 0ae5a4a7 e5ada6e9 82a3e4bc 9ae584bf efbc8ce8 b791e6ad a5efbc8c e8afbbe4 b9a6efbc 8ce994bb e782bce6 8891e5b0 b1e5b7b2 e7bb8fe9 9d9ee5b8 b8e6b885 e6a59ae6 8891e683 b3e8a681 e79a84e6 98afe4bb 80e4b988 e6a0b7e7 9a84e8b7 afefbc8c e99c80e8 a681e980 9ae8bf87 e4bb80e4 b988e6a0 b7e79a84 e58aaae5 8a9be58e bbe588b0 e8bebee3 8082e588 b0e4bb8a e5a4a9e6 9bb4e698 afe5a682 e6ada4ef bc8ce5a5 bde79a84 e4babae7 949fe79a 84e5a49a e6b2a10a e4bd86e4 bda0e4bb ace4b88d e79fa5e9 8193efbc 8ce69c89 e697b6e5 8099e79c 9fe79a84 e8a789e5 be97efbc 8ce4b880 e69dafe8 8cb6efbc 8ce784b6 e5908ee4 b880e9a6 96e5969c e6aca2e7 9a84e6ad 8cefbc8c e5b0b1e8 83bde6bb a1e8b6b3 e68980e6 9c89e380 82e7acac e4ba8ce6 aca1e7bb 93e69d9f efbc81ef bc81efbc 81656e64 656e6474 776f20e6 ad8cefbc 8ce5b0b1 e883bde6 bba1e8b6 b3e68980 e69c89e3 8082e7ac ace4ba8c e6aca1e7 bb93e69d 9fefbc81 efbc81ef bc81656e 64656e64 74776f20 e68891e8 82afe5ae 9ae593aa e4b880e6 a0b7e983 bde5819a e4b88de5 a5bde380 82e59084 e4bd8def bc8ce4bd a0e4bbac e4b880e5 ae9ae8a6 81e79fa5 e98193e8 87aae5b7 b1e683b3 e8a681e4 bb80e4b9 88efbc81 0a0a0a0a e5a4a7e5 ada6e982 a3e4bc9a e584bfef bc8ce8b7 91e6ada5 efbc8ce8 afbbe4b9 a6efbc8c e994bbe7 82bce688 91e5b0b1 e5b7b2e7 bb8fe99d 9ee5b8b8>


实际接收总包长度:5892, 当前接收包长度:292, 读取头部占用长度: 2, 读取内容长度:5890, 当前包字节:
<e6b885e6 a59ae688 91e683b3 e8a681e7 9a84e698 afe4bb80 e4b988e6 a0b7e79a 84e8b7af efbc8ce9 9c80e8a6 81e9809a e8bf87e4 bb80e4b9 88e6a0b7 e79a84e5 8aaae58a 9be58ebb e588b0e8 bebee380 82e588b0 e4bb8ae5 a4a9e69b b4e698af e5a682e6 ada4efbc 8ce5a5bd e79a84e4 babae794 9fe79a84 e5a49ae6 b2a10ae4 bd86e4bd a0e4bbac e4b88de7 9fa5e981 93efbc8c e69c89e6 97b6e580 99e79c9f e79a84e8 a789e5be 97efbc8c e4b880e6 9dafe88c b6efbc8c e784b6e5 908ee4b8 80e9a696 e5969ce6 aca2e79a 84e6ad8c efbc8ce5 b0b1e883 bde6bba1 e8b6b3e6 8980e69c 89e38082 e7acace4 ba8ce6ac a1e7bb93 e69d9fef bc81efbc 81efbc81 656e6465 6e647477 6f180122 0c64656e 67736f6e 676e616e 782a0030 0038aec2 e0d7b72b>

 --------------------- print log test end --------------------- 

示例demo下载地址:https://github.com/xiaotanit/Tan_ProtocolBuffer

 原文链接:http://www.cnblogs.com/tandaxia/p/6718695.html

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #3c828b } span.s1 { }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JavaEE

mybatis-plus的使用 ------ 进阶

关于mybatis-plus的简介以及基本使用,我在《mybatis-plus的使用 ------ 入门》一文中已做介绍,此处不再赘述。本文主要对mybatis...

94470
来自专栏大内老A

认识ASP.NET MVC的5种AuthorizationFilter

在总体介绍了筛选器及其提供机制(《深入探讨ASP.NET MVC的筛选器》)之后,我们按照执行的先后顺序对四种不同的筛选器进行单独介绍,首先来介绍最先执行的Au...

26460
来自专栏chenssy

如何扩展和优化线程池?

多线程的软件设计方法确实可以最大限度的发挥现代多核处理器的计算能力,提高生产系统的吞吐量和性能。但是,如果一个系统同时创建大量线程,线程间频繁的切换上下文导致的...

16520
来自专栏jeremy的技术点滴

Retrying_Library_For_Java

35650
来自专栏Java成神之路

【转】 Java 多线程之一

进程:一个计算机程序的运行实例,包含了需要执行的指令;有自己的独立地址空间,包含程序内容和数据;不同进程的地址空间是互相隔离的;进程拥有各种资源和状态信息,包括...

12330
来自专栏desperate633

Java并发之“饥饿”和“公平锁”(Starvation and Fairness)java中发生线程饥饿的原因java中实现公平锁公平锁性能考虑

如果一个线程的cpu执行时间都被其他线程抢占了,导致得不到cpu执行,这种情况就叫做“饥饿”,这个线程就会出现饥饿致死的现象,因为永远无法得到cpu的执行。解决...

16910
来自专栏LanceToBigData

JavaWeb(一)Servlet中的request与response

一、HttpServletRequest概述 1.1、HttpServletRequest简介   HttpServletRequest对象代表客户端的请求,当...

31680
来自专栏飞雪无情的博客

Go语言经典库使用分析(二)| Gorilla Context

在Go1.7之前,Go标准库还没有内置Context的时候,如果我们想在一个Http.Request里附加值,怎么做呢?一般都是Map对象,存储对应的Reque...

21830
来自专栏微服务那些事儿

java多线程(一)快速认识线程

答:继承Thread类,实现Runnable接口,为了展示自己学识的渊博,还可能还会说实现Callable接口通过FutureTask包装器来创建Thread线...

17440
来自专栏IT技术精选文摘

Java并发入门指南

关于Java并发 从创建起,Java已经支持核心的并发概念,如线程和锁。本指南帮助Java开发人员使用多线程程序来了解核心并发概念以及如何应用它们。本指南涵盖...

23990

扫码关注云+社区

领取腾讯云代金券