ProtocolBuffer 无法定义数据,尽管它被接收
ProtocolBuffer can't define data although it is received
我正在尝试使用谷歌的协议缓冲区发送/接收服务器/客户端架构中的数据。我能够连接两个与winsock,我能够从协议缓冲区发送和接收数据与它,但似乎有一个问题与反序列化服务器上的数据(我还没有做相反的,所以我不能告诉如果这工作尚未)
下面是我用来创建要发送到服务器的数据样本包的代码:MessageID *message = new MessageID();
message->set_type(MessageID::Type::MessageID_Type_PLAYERDATA);
PlayerData::Vector2 *position = new PlayerData::Vector2();
position->set_x(10.0f);
position->set_y(25.0f);
PlayerData *data = new PlayerData();
data->set_health((UINT32)50);
data->set_allocated_position(position);
auto inventory = data->add_items();
inventory->set_itemid((INT32)1);
inventory->set_count((INT32)5);
message->set_allocated_playerdata(data);
m_pNetworkObject->Send(message);
这是实际通过TCP连接发送数据的代码:
// Serialize to string.
std::string sendData;
data->SerializeToString(&sendData);
// Convert data to const char*
const char* dataToSend = sendData.c_str();
int iResult;
iResult = send( ConnectSocket, dataToSend, data->ByteSize(), 0 );
if (iResult == SOCKET_ERROR)
{
printf("send failed with error: %dn", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
exit(1);
}
所以,这是在客户端运行的代码。现在,当我在服务器上收到此消息时,我从ProtocolBuffer中得到以下错误:
Can't parse message of type "MessageID" because it is missing required fields: type
Can't parse message of type "PlayerData" because it is missing required fields: Position, Health
服务器上反编译winsock数据的代码如下:
// decompile to a proto file and check ID
MessageID* receivedData = new MessageID();
receivedData->ParseFromArray(&recv, strlen(recv));
// check and redeserialize
switch (receivedData->type())
{
case MessageID::Type::MessageID_Type_PLAYERDATA:
{
PlayerData* playerData = new PlayerData();
playerData->ParseFromArray(&recv, strlen(recv));
UsePlayerData(sock, playerData);
break;
}
case MessageID::Type::MessageID_Type_WORLDDATA:
{
WorldData* worldData = new WorldData();
worldData->ParseFromArray(&recv, strlen(recv));
UseWorldData(sock, worldData);
break;
}
}
奇怪的是,虽然错误说数据不包含Type值,但它确实将其设置为1,并且switch语句有效。之后,当我试图查看位置和健康数据时,一切都是0。
我不知道我做错了什么。我读了大部分协议缓冲区教程和帮助,但似乎无济于事。
编辑:我尝试在同一个应用程序中对数据进行序列化和反序列化(不涉及网络),并且使用以下代码可以做到这一点:
std::string sendData;
message->SerializeToString(&sendData);
MessageID* receivedData = new MessageID();
receivedData->ParseFromString(sendData);
如果我检查receivedData中的数据,它与原始对象"message"中的数据完全相同(因此,正确的值)
您的问题是您正在使用strlen()
来查找消息的长度。strlen()
只查找第一个零值字节,并假设这是结束。这是文本字符串的约定,但不适用于像协议缓冲区这样的二进制消息。在这种情况下,strlen()
返回的大小太短,因此消息中缺少一些字段,但相反的情况也可能发生——strlen()
可以运行缓冲区的末尾并返回一个太长的大小,甚至使您的程序崩溃。
因此,您需要确保消息的实际大小从发送者传达给接收者。
相关文章:
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- 通过 NIF 从C++返回自定义数据结构
- 我们可以在套接字编程中将自定义数据作为辅助数据发送吗?
- ClassTemplateSpecializationDecl 的定义数据为 null
- 自定义数据结构的优点是什么?
- 如何在 omnet++ 中发送自定义数据包?
- 错误 - 自定义数据类型作为有效负载,带有提升::几何
- C++哈希表 - 如何解决自定义数据类型作为键的unordered_map冲突?
- 从自定义数据类型向量中删除重复元素
- C++:自定义数据类型向量错误的队列
- 交换未定义数据类型中的字节顺序
- 在 C++ 中设置的用户定义数据类型
- C++ - 按自定义数据类型向量的值删除元素
- 通过套接字发送的自定义数据包
- 以面向对象的方式解析自定义数据包
- 异步发送和接收带有提升的自定义数据包?
- 使用算法标头查找自定义数据类型的minmax
- 仅覆盖自定义数据架构的迭代器的操作员*()
- 有没有办法将大小传递给节点(C++自定义数据容器)中的数组
- 如何将自定义数据类型(用std::对填充的std::数组)写入文件流