CocoaAsyncSocket + Protobuf 處理粘包和拆包問題

来源:http://www.cnblogs.com/tandaxia/archive/2017/04/16/6718695.html
-Advertisement-
Play Games

在上一篇文章《iOS之ProtocolBuffer搭建和示例demo》分享環境的搭建, 我們和伺服器進行IM通訊用了github有名的框架CocoaAsynSocket, 然後和伺服器之間的數據媒介是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];
    [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{
    //...
}
View Code

 

--------------------- 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>
View Code

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

 

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

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上回書說道,JS中變數、運算符、分支結構、迴圈和嵌套迴圈等內容。本回就由本K給大伙嘮嘮JS中的BOM、DOM和事件。 一、“花心大蘿蔔”——BOM 1、震驚,FFF團為何對BOM舉起了火把——BOM簡介 BOM(Browser Object Model) 是指瀏覽器對象模型,在JS中BOM是個不折不 ...
  • 一個精美的網頁需要的樣式很多,在父級上設置的字體顏色或者大小,在其子元素中不一定全部相同,這時候要更改其中某一項的樣式怎麼辦呢。 很多新手朋友就不明白,會迷惑為什麼我使用class單獨命名了,重新設置了還是沒有變化,會考慮是不是格式錯了,是不是命名有問題,但是有沒有考慮過權重值呢,新手朋友對於權重值 ...
  • opacity透明在網頁製作中使用會很多,為了增加好看的效果,透明的樣式肯定是必不可少的。 記得之前做一個網頁,其中一個塊給了個30的高,背景半透明的黑色,上面有一排導航,導航字體的顏色也就成了灰黑色,本來是想做成白色字體,怎麼改都不行,以為是字體的ul層在背景塊的下麵,想用z-index把字體的層 ...
  • 通過JS實現banner圖的滾動主要是定時器的應用 先新建好banner圖的幾張圖片,最後一張與第一張用同一個,保證滾動的不間斷 改好樣式,需註意所有圖片要在同行顯示,否則不能向左滾動 聲明一個函數,為定時器函數,函數內通過switch結構執行,case的值通過聲明一個全局變數每次執行函數的時候使其 ...
  • DOM對象模型 【DOM樹節點】 DOM節點分為三大類:元素節點,文本節點,屬性節點: 文本節點,屬性節點為元素節點的兩個子節點; 通過getElment系列方法,可以去到元素節點; 【查看節點】 1.getElementById:通過id獲取唯一的節點;多個同名ID只會取到第一個; 2.etEle ...
  • 之前的某次番嗇看到油管上有這麼一個進度條,當時覺得挺好玩,一直想著做一個試試,剛纔弄了一下寫了一個不算太好看的簡陋版本,哈哈。 (本博客刷新會頭部會出現,因為並沒有真正的參與到瀏覽器載入是否完整這個渲染過程中來,所以只是一個表象,並不是說這個顯示完了就瀏覽器也載入完了所以資源。) ...
  • 一、簡介及安裝: gulp是前端開發過程中對代碼進行構建的工具,是自動化項目的構建利器;她不僅能對網站資源進行優化,而且在開發過程中很多重覆的任務能夠使用正確的工具自動完成;使用她,我們不僅可以很愉快的編寫代碼,而且大大提高我們的工作效率 gulp的優點:基於流的操作、任務化。 常用api:src ...
  • 雪花飄落的效果實現步驟:1.使用setInterval定時器每800毫秒創建一個雪花;2.把每一個雪花作為參數傳進動態下落的方法中即可。 js實現代碼: 效果圖如下: 這樣雪花飄落的效果就做好了。有什麼不足的地方請指正! ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...