Message Data{
optional uint64 userid = 1;
repeated string usernames = 2;
optional uint32 status = 3;
}情况1-“状态”包含非零值“”
如果在使用data__pack(const * message,uint8_t * out)函数打包数据时,status =非零值,则“out”的长度为100,函数返回100 (以值100为例)。
案例2-“状态”包含值0
当我使用data__pack()函数打包数据时,如果status =0(对于与第1种情况相同的userid和username的值),'out‘的长度是99,但函数仍然返回100。
如果您注意到上面的2种情况,如果变量“status”使用的值为0,则输出缓冲区的长度总是比如果“status”包含非零值的长度少1。我已经将has_status变量设置为1,所以这似乎不是一个问题。
这是原虫还是我做错了什么?
详细信息:我使用的 Protobuf版本- protobuf-c-0.15
关于发行的详细信息
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);我使用data__get_packed_size()来获得大小。在向预定接收方发送HTTP请求时,我发送内容长度为“buf_len”,而“buf”用于HTTP主体。
Content-Length: 100
Content-Type: application/protobuf
<Body containing the protobuf encoded data - seems to have 99 bytes>接收器现在继续等待,直到它接收到完整的请求(即100),并且连接超时。在这种情况下,接收方如何知道如何处理这个问题,因为它只会等待100的内容长度被接收?
发布于 2014-03-29 04:19:50
编码uint32需要两个变量,每个变量至少有一个字节长。第一个字节包含编码(“有线”)类型和标记号,如果标记最多为15,则长度为1字节。第二个变量是整数本身,如果整数最多为127,则长度为1字节。省略("defaulted")可选字段根本不占用任何字节;省略字段不会在线路上以任何方式编码;必须推导它们的缺位。
因此,如果省略可选的uint32字段,则有线编码将至少比包含可选字段的相同的原型短两个字节。
您没有说明如何计算“out”的长度。唯一正确的方法是在打包data__get_packed_size对象之前调用data。不过,我猜您使用的是strlen(out),这不会产生正确的结果。strlen只能用于字符串;更具体地说,它只能在NUL-terminated strings上使用,因为它在碰到NUL (0)字节时停止计数,如果没有看到NUL字节,则会产生未定义的行为。不能对任意二进制数据使用strlen。
在protobuf编码中,标记为3和值为0的显式uint32将被编码为0x18 0x00,而标记为3和值为42的显式uint32将被编码为0x18 0x2A。如果数据编码中早期没有空值,那么0编码的第二个字节将终止strlen的计数。在某些理想情况下(例如,缓冲区足够长,并在将消息打包到它之前被清除到所有NUL),strlen将报告以0为一个“字符”的原型的长度,这个“字符”比42的protobuf短,因为0编码中的NUL发生在消息的末尾,导致strlen提前停止精确计数一个字节。
这是一种解释,不是解决办法。不要在不以NUL结尾的字符串上使用strlen。
https://stackoverflow.com/questions/22726495
复制相似问题