c++ - 使用 Qt 跨 HTTP Protocol Buffer 序列化中的空白

标签 c++ qt http serialization protocol-buffers

我正在尝试通过 HTTP 连接发送一个 Google Protocol Buffer 序列化字符串,然后将其接收回来(未修改),我将在其中对其进行反序列化。我的问题似乎与“serializeToString”方法有关,该方法采用我的字符串并似乎将换行符(可能还有其他空格)添加到序列化字符串中。在下面的示例中,我使用字符串“camera_stuff”,在对其进行序列化之后,我得到了一个前面带有换行符的 QString。我尝试了其他字符串,结果相同,只是添加了不同的空格和换行符。这会导致我的反序列化操作出现问题,因为 HTTP 请求中未捕获空格,因此无法成功解码包含来自服务器的序列化字符串的响应。如果我猜到序列化字符串中的空格,我可以部分解码它。我该如何解决这个问题?请查看以下代码 - 谢谢。

我有一个 Protocol Buffer .proto 文件,如下所示:

message myInfo {
  required string data = 1;
  required int32 number = 2;
}

运行protoc编译器后,我在其中构造Qt,如下所示:

// Now Construct our Protocol Buffer Data to Send
myInfo testData;
testData.set_data("camera_stuff");
testData.set_number(123456789);

我将我的数据序列化为这样的字符串:

// Serialize the protocol buffer to a string
std::string serializedProtocolData; // Create a standard string to serialize the protocol buffer contents to
myInfo.SerializeToString(&serializedProtocolData); // Serialize the contents to the string
QString serializedProtocolDataAsQString = QString::fromStdString(serializedProtocolData);

然后我像这样打印出来:

// Print what we are sending
qDebug() << "Sending Serialized String: " << serializedProtocolDataAsQString;
qDebug() << "Sending Serialized String (ASCII): " << serializedProtocolDataAsQString.toAscii();
qDebug() << "Sending Serialized String (UTF8): " << serializedProtocolDataAsQString.toUtf8();
qDebug() << "Sending Serialized Protocol Buffer";
qDebug() << "Data Number: " << QString::fromStdString(myInfo.data());
qDebug() << "Number: " << (int)myInfo.number();

当我将数据作为 HTTP 多部分消息的一部分发送时,我看到这样的打印语句(注意打印输出中的换行符!):

Composing multipart message...
Sending Serialized String:  "

camera_stuffï:" 
Sending Serialized String (ASCII):  "

camera_stuffï:" 
Sending Serialized String (UTF8):  "

camera_stuffÂÂï:" 
Sending Serialized Protocol Buffer 
Data:  "camera_stuff" 
Number:  123456789 
Length of Protocol Buffer serialized message:  22 
Loading complete...

客户端像这样反序列化消息:

// Now deserialize the protocol buffer
string = "\n\n" + string; // Notice that if I don't add the newlines I get nothing!
myInfo protocolBuffer;
protocolBuffer.ParseFromString(string.toStdString().c_str());
std::cout << "DATA: " << protocolBuffer.model() << std::endl;
std::cout << "NUMBER: " << protocolBuffer.serial() << std::endl;
qDebug() << "Received Serialized String: " << string;
qDebug() << "Received Deserialized Protocol Buffer";
qDebug() << "Data: " << QString::fromStdString(protocolBuffer.data());
qDebug() << "Number: " << (int)protocolBuffer.number();

服务器返回它而不对序列化字符串做任何事情,客户端打印如下:

RESPONSE:  "camera_stuffï:"  
DATA: camera_stu
NUMBER: 0
Received Serialized String:  "

camera_stuffï:" 
Received Deserialized Protocol Buffer 
Number:  "camera_stu"

Number:  0

所以你看到的问题是我无法猜测空格,所以我似乎无法可靠地反序列化我的字符串。有什么想法吗?

最佳答案

序列化的 protobuf 不能被视为 C 字符串,因为它可能在其中嵌入了 NUL。它是一种二进制协议(protocol),它使用所有可能的八位字节值,并且只能通过 8 位干净连接发送。它也不是有效的 UTF-8 序列,不能作为 Unicode 序列化和反序列化。所以 QString 也不是存储序列化 protobuf 的有效方式,我怀疑这也可能给您带来问题。

您可以使用 std::stringQByteArray。我强烈建议你避免任何其他事情。特别是,这是错误的:

protocolBuffer.ParseFromString(string.toStdString().c_str());

因为它会在第一个 NUL 处截断 protobuf。 (你的测试消息没有,但这迟早会咬你一口。)

至于通过 HTTP 发送消息,您需要能够确保消息中的所有字节都按原样发送,这也意味着您需要明确发送长度。您没有包含实际传输和接收消息的代码,所以我无法对此发表评论(无论如何我都不太了解 Qt HTTP 库),但 0x0A are being deleted 从消息的前面表明您丢失了一些东西。确保正确设置消息部分中的内容类型(例如,不是文本)。

关于c++ - 使用 Qt 跨 HTTP Protocol Buffer 序列化中的空白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13070592/

相关文章:

c++ - 如何正确地将接口(interface)委托(delegate)给 C++ 中的姊妹类?

javascript - 如何在angularjs中调试$http方法

c++ - C++20 是否为 "overflow"的有符号整数很好地定义了左移?

c++ - 非类类型成员getName请求错误 'char'

Qtreeview,选中时调整线的大小

c++ - 将 openCV .dll 文件添加到 Netbeans C++ Qt 应用程序

mysql - 静态构建 Qt 时找不到 libmysql.dll

http - 使用 groovy 和数据发送 POST 已经进行了 URL 编码

HTTP 后跟四个斜杠?

c++ - - 内联函数 g++4.9.2 中的 Warray-bounds 虚假警告