我正在尝试通过HTTP连接发送一个Google Protocol Buffer序列化字符串,然后将其接收(未修改),我将对其进行反序列化。我的问题似乎是'serializeToString'方法,它采用我的字符串,似乎在序列化字符串中添加换行符(可能还有其他空格)。在下面的例子中,我正在使用字符串“camera_stuff”,在序列化之后,我得到一个前面有换行符的QString。我已经尝试了其他字符串,只有不同的空格和添加的换行符才能得到相同的结果。这导致我的反序列化操作出现问题,因为在HTTP请求中没有捕获空格,因此无法成功解码包含来自服务器的序列化字符串的响应。如果我猜测序列化字符串中的空格,我可以部分解码它。我怎么解决这个问题?请参阅以下代码 - 谢谢。
我有一个协议缓冲区.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
所以你看到的问题是我无法猜出空白,所以我似乎无法可靠地反序列化我的字符串。有什么想法吗?
答案 0 :(得分:2)
序列化的protobuf不能被视为C
字符串,因为它可能嵌入了NUL。它是一个二进制协议,它使用每个可能的八位字节值,并且只能通过8位干净连接发送。它也不是有效的UTF-8序列,不能作为Unicode序列化和反序列化。所以QString
也不是存储序列化protobuf的有效方法,我怀疑这也可能导致你的问题。
您可以使用std::string
和QByteArray
。我强烈建议你避免其他任何事情。特别是,这是错误的:
protocolBuffer.ParseFromString(string.toStdString().c_str());
因为它会在第一个NUL
截断protobuf。 (你的测试信息没有,但这迟早会咬你。)
对于通过HTTP发送消息,您需要能够确保消息中的所有字节按原样发送,这也意味着您需要显式发送长度。你没有包含实际发送和接收消息的代码,因此我无法对其进行评论(我不知道Qt HTTP库在任何情况下都是如此),但事实是0x0A
从邮件正面删除表明你遗漏了一些东西。确保正确设置消息部分中的内容类型(例如,不是文本)。