如何将Protobuf消息编码为字节通过HTTP传输(C++场景)
Protobuf消息二进制编码与HTTP传输问题解决
问题场景
定义的Protobuf消息(.proto文件)
syntax = "proto3"; message Foo { int32 num = 1; string fooString = 2; }
C++序列化代码
Foo foo; foo.set_num(1); foo.set_fooString("foo_as_string"); std::string fooAsString; foo.SerializeToString(&fooAsString);
异常现象
将序列化后的fooAsString通过HTTP发送后,接收端收到的不是Protobuf二进制字节,而是直接的字段值:
foo_as_string 1
解决方法
SerializeToString本身是正确的——它已经把Protobuf消息序列化为二进制字节并存储在std::string中(std::string支持存储任意二进制数据,包括非ASCII字节)。问题出在HTTP传输环节没有正确处理二进制数据,需要做以下调整:
设置正确的HTTP请求头
必须将Content-Type设置为二进制类型,比如application/octet-stream或application/protobuf,避免服务器或中间件把数据当作文本解析。示例代码(以libcurl为例):struct curl_slist* headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/octet-stream"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);直接发送二进制数据
发送HTTP请求时,要传递字符串的原始二进制数据和长度,而不是当作文本处理。比如用libcurl时,指定数据指针和大小:curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fooAsString.data()); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, fooAsString.size());接收端正确解析二进制数据
接收方需要读取原始二进制字节流,再用Protobuf的ParseFromString或ParseFromArray方法反序列化,而不是将收到的数据当作文本打印或处理。
内容的提问来源于stack exchange,提问作者MLev
相关产品推荐
相关产品推荐

