ProtocolBuffer缺少必需的字段,但这些字段已填充
ProtocolBuffer missing required fields but they are filled in
我正在创建一个客户端-服务器环境,我刚刚实现了UDP。我之前只使用TCP连接进行工作和测试,然后一切都很好。现在,如果我试图从客户端向服务器发送数据包,我会得到一个错误,即一些必需的字段没有填写清楚(请参阅后面的代码)。我真的不知道为什么会发生这种情况,因为它以前是有效的。
我想有一件事可能很重要,TCP套接字和UDP套接字的接收方法在不同的线程上。(服务器使用多线程)
所以,这里有一些代码:
TCP接收(部分):
iResult = recv(m_Connections[t].socket, m_TCPRecvbuf, m_TCPRecvbuflen, 0);
// Deserialize the data
MessageID* receivedData = new MessageID();
receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize());
一开始我用iResult在ParseFromArray中计算大小(这似乎有效),但我更改了它,所以我把大小放在了数据本身中。(现在已被接收数据->packetsize())
UDP接收(部分)在另一个线程上:
iResult = recvfrom(m_UDPListenSocket, m_UDPRecvbuf, m_UDPRecvbuflen, 0, (struct sockaddr *)&address, &addrlen);
// Deserialize the data
MessageID* receivedData = new MessageID();
receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize());
这是第一次创建发送的数据包:
void NetworkInterface::SendLoginData(string username, string password)
{
// Create base message
// -----------------
MessageID message;
message.set_type(MessageID::Type::MessageID_Type_LOGINDATA);
// Create logindata
// ------------------
LoginData data = message.logindata();
data.set_username(username);
data.set_password(password);
// Create packet
// ----------------------
int size = message.ByteSize();
void* buffer = malloc(size);
message.set_packetsize(size);
message.set_clientid(0);
message.SerializeToArray(buffer, size);
if (m_pTCPNetworkingObject != nullptr)
m_pTCPNetworkingObject->SendData(buffer, size);
else
printf("NetworkInterface [ERROR]: No connection data was found. Please use CreateConnectionObject() first!n");
}
之后它给出的错误是Type、ClientID和packetSize字段丢失,但您可以在中看到这些字段已填充
下面是SendData()方法:
void SendData(void* data, int size)
{
// SEND DATA
int iResult;
iResult = send(m_TCPConnectSocket, (char*)data, size, 0 );
if (iResult == SOCKET_ERROR)
printf("send failed with error: %dn", WSAGetLastError());
}
这是关于我能提供的所有信息。感谢您的帮助。
存在多个问题:
1) 反序列化:
receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize());
在parseFromArray
填充之前调用packetSize
,请改用iResult
。
2) 登录数据:
LoginData data = message.logindata();
这会读取一份空loginData的邮件副本,您永远不会更改message
。使用
LoginData* data = message.mutable_logindata();
获取指向消息loginData的指针并在message
中对其进行修改。
3) 序列化:
int size = message.ByteSize();
void* buffer = malloc(size);
这使用了空邮件的大小(因为未设置loginData)。所以你永远不会发送完整的信息。设置完所有属性后,必须调用ByteSize()
。这与消息中的packetSize相矛盾。由于无论如何都不能将其用于反序列化(请参见1),因此应该删除此条目。
相关文章:
- 将结构字段的类型展开为可变模板参数
- 将位字段导出到数组
- 为了方便起见,我应该避免公开私有字段变量吗
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- sizeof 函数如何在带和不带位字段的结构上工作?(填充)
- 使用 cin >> 和 cout <<填充类C++的字段
- C 如何从UCHAR数组中填充结构的位字段
- 在 C++ 中填充重复的自定义协议缓冲区字段
- 使用out类型转换,我如何填充位字段
- 当您有结构名称和字段值的列表时,是否可以以编程方式创建结构的对象并填充字段
- C++结构填充和字段打包
- 如何查找和填充第三方源的 Flash 字段
- 有没有办法控制C++中结构成员(包括位字段)之间的填充
- ProtocolBuffer缺少必需的字段,但这些字段已填充
- 在Blackberry Cascades 10(C++、Qt、QML)中,如何在填充字段的情况下调用电子邮件客户端
- Gcc /clang在基结构的后填充中布局派生结构的字段
- 如何删除空字段(或填充了不正确的数据)
- 只有在填充了两个字段时才启用按钮
- 在循环中填充C++对象字段会导致空字段
- 通过返回的指针填充私有字段