2013-11-03 37 views
5

我需要從C/C++的linux套接字中讀取VarInts。任何圖書館,想法或什麼?從linux套接字讀取「varint」

我嘗試閱讀和鑄造焦炭爲bool [8]嘗試沒有成功讀取VarInt ...

而且,這是一個新的Minecraft 1.7.2通信協議兼容性,因此,也the documentation of the protocol可能幫幫我。

讓我解釋一下我的項目:我正在製作一個Minecraft服務器軟件來運行在我的VPS中(因爲java太慢了......),並且我被這個協議困住了。一個線程等待連接,當它有一個新連接時,它創建一個新的Client對象並啓動開始與客戶端通信的客戶端線程。

我認爲沒有必要顯示代碼。如果我錯了,告訴我,我會用一些代碼編輯。

+2

我以前從來沒見過varints,但我想谷歌的「varint C庫」,並得到了一些打擊。 –

回答

11

首先,請注意varints作爲實際字節發送,而不是字符10的字符串。

對於一個無符號的varint,我相信下面的代碼會爲你解碼,假設你已經在data指向的緩衝區中獲得了varint數據。該示例函數返回參考參數int decoded_bytes中解碼的字節數。

uint64_t decode_unsigned_varint(const uint8_t *const data, int &decoded_bytes) 
{ 
    int i = 0; 
    uint64_t decoded_value = 0; 
    int shift_amount = 0; 

    do 
    { 
     decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;  
     shift_amount += 7; 
    } while ((data[i++] & 0x80) != 0); 

    decoded_bytes = i; 
    return decoded_value; 
} 

要解碼簽署varint,您可以使用調用第一第二個功能:

int64_t decode_signed_varint(const uint8_t *const data, int &decoded_bytes) 
{ 
    uint64_t unsigned_value = decode_unsigned_varint(data, decoded_bytes); 
    return (int64_t)(unsigned_value & 1 ? ~(unsigned_value >> 1) 
             : (unsigned_value >> 1)); 
} 

我相信這兩個功能是正確的。我使用下面的代碼進行了一些基本測試,以驗證Google頁面中的幾個數據點。輸出是正確的。

#include <stdint.h> 
#include <iostream> 


uint64_t decode_unsigned_varint(const uint8_t *const data, int &decoded_bytes) 
{ 
    int i = 0; 
    uint64_t decoded_value = 0; 
    int shift_amount = 0; 

    do 
    { 
     decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;  
     shift_amount += 7; 
    } while ((data[i++] & 0x80) != 0); 

    decoded_bytes = i; 
    return decoded_value; 
} 

int64_t decode_signed_varint(const uint8_t *const data, int &decoded_bytes) 
{ 
    uint64_t unsigned_value = decode_unsigned_varint(data, decoded_bytes); 
    return (int64_t)(unsigned_value & 1 ? ~(unsigned_value >> 1) 
             : (unsigned_value >> 1)); 
} 



uint8_t ex_p300[] = { 0xAC, 0x02 }; 
uint8_t ex_n1 [] = { 0x01 }; 

using namespace std; 

int main() 
{ 
    int decoded_bytes_p300; 
    uint64_t p300; 

    p300 = decode_unsigned_varint(ex_p300, decoded_bytes_p300); 

    int decoded_bytes_n1; 
    int64_t n1; 

    n1 = decode_signed_varint(ex_n1, decoded_bytes_n1); 

    cout << "p300 = " << p300 
     << " decoded_bytes_p300 = " << decoded_bytes_p300 << endl; 

    cout << "n1 = " << n1 
     << " decoded_bytes_n1 = " << decoded_bytes_n1 << endl; 

    return 0; 
} 

要編碼varints,可以使用以下函數。請注意,緩衝區uint8_t *const data應該至少有10個字節的空間,因爲最大的varint長度爲10個字節。
的#include

// Encode an unsigned 64-bit varint. Returns number of encoded bytes. 
// 'buffer' must have room for up to 10 bytes. 
int encode_unsigned_varint(uint8_t *const buffer, uint64_t value) 
{ 
    int encoded = 0; 

    do 
    { 
     uint8_t next_byte = value & 0x7F; 
     value >>= 7; 

     if (value) 
      next_byte |= 0x80; 

     buffer[encoded++] = next_byte; 

    } while (value); 


    return encoded; 
} 

// Encode a signed 64-bit varint. Works by first zig-zag transforming 
// signed value into an unsigned value, and then reusing the unsigned 
// encoder. 'buffer' must have room for up to 10 bytes. 
int encode_signed_varint(uint8_t *const buffer, int64_t value) 
{ 
    uint64_t uvalue; 

    uvalue = uint64_t(value < 0 ? ~(value << 1) : (value << 1)); 

    return encode_unsigned_varint(buffer, uvalue); 
} 
+1

感謝那個巨大的答案。也許我是脫離主題,但是,我如何編碼?我想我應該看看位操作符... – azteca1998

+1

編碼類似於解碼。我將掀起一對編碼功能並將它們扔到那裏。 –

+0

再次感謝!我不需要保留10個字節,因爲我正在修改函數來發送構建的varint。該函數將從循環的每一步向客戶端發送1個字節。 – azteca1998