在protobuf-c中,可选uint32变量的值是否为0
案例1-“状态”包含非零值“ 如果状态=非零值 当我使用data_uupack(const data*message,uint8_t*out)函数打包数据时,“out”的长度为100,函数返回100(值100用作示例) 案例2-“状态”包含值0 如果status=0(对于与案例1相同的userid和username值) 当我使用data\uuu pack()函数打包数据时,“out”的长度是99,但函数仍然返回100 如果您注意到上述两种情况,如果变量“status”使用的值为0,则输出缓冲区的长度始终比“status”包含非零值时的长度小1。我已经将has_status变量设置为1,所以这似乎不是问题 这是protobuf bug还是我做错了什么 其他详细信息:我正在使用的Protobuf版本-Protobuf-c-0.15 有关该问题的其他详细信息在protobuf-c中,可选uint32变量的值是否为0,c,protocol-buffers,C,Protocol Buffers,案例1-“状态”包含非零值“ 如果状态=非零值 当我使用data_uupack(const data*message,uint8_t*out)函数打包数据时,“out”的长度为100,函数返回100(值100用作示例) 案例2-“状态”包含值0 如果status=0(对于与案例1相同的userid和username值) 当我使用data\uuu pack()函数打包数据时,“out”的长度是99,但函数仍然返回100 如果您注意到上述两种情况,如果变量“status”使用的值为0,则输出缓冲区的
Message Data{
optional uint64 userid = 1;
repeated string usernames = 2;
optional uint32 status = 3;
}
我使用data\uu get\u packeted\u size()来获取大小。通过HTTP请求发送到预期的接收者时,我发送的内容长度为'buf_len','buf'用于HTTP正文
Data msg = DATA__INIT;
void* buf = (void*) NULL;
int buf_len = 0;
buf_len = data__get_packed_size(&msg);
buf = (void*) malloc(buf_len+1);
data__pack(&msg, buf);
内容长度:100
内容类型:应用程序/协议
接收器现在继续等待,直到它接收到完整的请求(即100),并且连接最终超时。
在这种情况下,接收器如何知道如何处理这一问题,因为它只等待接收到长度为100的内容?编码
uint32
需要两个变量,每个变量至少有一个字节长。第一个字节包含编码(“导线”)类型和标签号,如果标签最多为15,则长度为一个字节。第二个变量是整数本身,如果整数最多为127,则长度为一个字节。省略的(“默认”)可选字段根本不占用任何字节;省略的字段不会以任何方式在导线上编码;必须推断他们的缺席
因此,如果省略可选的uint32
字段,则有线编码将比包含可选字段的相同protobuf至少短两个字节
您没有说明如何计算“out”的长度。唯一正确的方法是在打包数据
对象之前调用数据
获取打包大小。但是,我猜您使用的是strlen(out)
,这不会产生正确的结果strlen
只能用于字符串;更具体地说,它只能用于NUL终止的字符串
,因为它在命中NUL
(0)字节时停止计数,如果没有看到NUL
字节,则产生未定义的行为。不能对任意二进制数据使用strlen
在protobuf编码中,标签为3且值为0的显式uint32
将被编码为0x18 0x00
,而标签为3且值为42的显式uint32
将被编码为0x18 0x2A
。如果数据编码之前没有NUL,则0
编码的第二个字节将终止strlen
的计数。在某些理想情况下(例如,缓冲区足够长,并且在将消息打包到缓冲区之前清除为所有NUL
),strlen将0
的protobuf的长度报告为比42的protobuf短一个“字符”,因为0
编码中的NUL
发生在消息的末尾,导致strlen
提前一个字节停止计数
这是一种解释,不是一种解决办法。不要在不是以NUL结尾的字符串上使用strlen
。我想当可选值不存在时,它将被视为零。因此,在序列化过程中也可以省略零值。这能解释吗?你是对的。对不起,我没有提到完整的问题。我已经为这个问题添加了更多的细节。你有什么想法吗?@cdemon:你还是不解释为什么你认为out
只有99个字节?您如何通过HTTP连接将发送出去
?您使用的API是否仅适用于字符串(即,不需要您指定长度)?当我在接收方看到日志时,我看到它正在等待接收完整的内容长度。我正在使用libevent通过HTTP连接发送。我明白你的意思,你认为如果它只处理字符串,那么发送端会有问题吗?@cdemon:我绝对相信。但你在这里没有提供太多细节。您使用的是libevent
的简单HTTP服务器吗?另外,该API要求您提供一个evbuffer
。那么,您是如何创建evbuffer
?我需要深入研究遗留代码来找出这一点。。谢谢你的支持。如果我发现了什么,我会告诉你的。
Content-Length: 100
Content-Type: application/protobuf
<Body containing the protobuf encoded data - seems to have 99 bytes>