我需要从C/C++的Linux套接字读取VarInts。有图书馆,想法或其他东西吗?
我尝试读取char并将其转换为bool [8],但尝试读取VarInt却没有成功。
另外,这是为了与新的Minecraft 1.7.2通信协议(protocol)兼容,因此the documentation of the protocol也可能会有所帮助。
让我解释一下我的项目:我正在制作一个Minecraft服务器软件,以便在我的VPS中运行(因为Java太慢了……),而且我对协议(protocol)一无所知。一个线程等待连接,当它具有新连接时,它将创建一个新的Client对象,并启动Client线程,该线程开始与该客户端进行通信。
我认为没有必要显示代码。万一我错了,告诉我,我将用一些代码进行编辑。
最佳答案
首先,请注意,varint是作为实际字节发送的,而不是字符1
和0
的字符串发送的。
对于无符号varint,我相信以下内容将为您解码,假设您已将varint数据存储在data
指向的缓冲区中。此示例函数返回引用参数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;
}
要对varint进行编码,可以使用以下函数。请注意,缓冲区
uint8_t *const data
应该至少有10个字节的空间,因为最大的varint长为10个字节。#包括
// 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 );
}
关于c++ - 从Linux套接字读取 "varint",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19758270/