gpt4 book ai didi

c++ - 当服务器将数据作为 c 结构发送时,我们可以在客户端将缓冲区类型转换为 C++ 结构吗?

转载 作者:IT王子 更新时间:2023-10-29 00:45:23 26 4
gpt4 key购买 nike

我有用 C 语言编写的服务器和客户端进程,名为 NetworkServer.c 和 NetworkClient.c,这两个进程使用 linux 套接字进行通信。当客户端发送如下请求以获取以太网统计信息时,

// rxbuf - character array of 128K
// ETHERNET_DIAGNOSTIC_INFO - structure typedefed
recv(sockfd, rxbuf, sizeof(ETHERNET_DIAGNOSTIC_INFO), 0)

服务器将数据填充到 rxbuf(作为 ETHERNET_DIAGNOSTIC_INFO,因为服务器也使用定义此结构的头文件的相同拷贝)并发送数据。客户端接收到数据后,将进行如下类型转换以获取数据。

ETHERNET_DIAGNOSTIC_INFO *info = (ETHERNET_DIAGNOSTIC_INFO *) rxbuf;

结构在 NetworkDiag.h 中定义如下。

#ifdef __cplusplus
extern "C" {
#endif

typedef struct ETHERNET_DIAGNOSTIC_INFO
{
uint32_t cmdId;
unsigned long RxCount[MAX_SAMPLES];
unsigned long TxCount[MAX_SAMPLES];
time_t TimeStamp[MAX_SAMPLES] ;
char LanIpAddress[20];
char LanMacAddress[20];
char WanIpAddress[20];
char LanDefaultGateway[20];
char LanSubnetMask[20];
char LanLease[5000];
}ETHERNET_DIAGNOSTIC_INFO;

这工作正常。

现在有一个要求,我需要创建一个 c++ 文件,它应该作为客户端工作(我删除了客户端 C 文件,服务器应该保留为 c 文件)。我为结构定义定义了头文件,如下所示。

struct ETHERNET_DIAGNOSTIC_INFO
{
uint32_t cmdId;
unsigned long RxCount[MAX_SAMPLES];
unsigned long TxCount[MAX_SAMPLES];
time_t TimeStamp[MAX_SAMPLES] ;
char LanIpAddress[20];
char LanMacAddress[20];
char WanIpAddress[20];
char LanDefaultGateway[20];
char LanSubnetMask[20];
char LanLease[5000];
};

基本上我删除了 C++ 防护和 typedef 并使用 client.cpp 文件中的以下代码从服务器获取结果。

if(recv(sockfd, rxbuf, sizeof(ETHERNET_DIAGNOSTIC_INFO), 0) > 0)
{
ETHERNET_DIAGNOSTIC_INFO *info = reinterpret_cast<ETHERNET_DIAGNOSTIC_INFO *> (rxbuf);
}

我没有得到正确的结果。结构中的值放错了地方(有些值是正确的,但很多值放错了地方)。我也尝试了“C”类型转换,但没有用。

我怀疑当服务器以 C 结构发送数据时,我们不能在客户端将缓冲区类型转换为 C++ 结构。这是对的吗?谁能告诉我如何解决这个问题?

最佳答案

这种方法存在多个问题:

  1. Endianness服务器和客户端机器之间可能不同

    然后您需要对数字和 time_t 进行反序列化。

  2. Structure packing在服务器 (c++) 和客户端 (C) 上编译的代码可能不同

    然后您需要使用一种协议(protocol)来发送数据,例如二进制 ASN、protobuf 或许多其他协议(protocol)。

  3. if(recv(sockfd, rxbuf, sizeof(ETHERNET_DIAGNOSTIC_INFO), 0) > 0)无法保证 recv 将准确读取 sizeof(ETHERNET_DIAGNOSTIC_INFO) 字节。

    您需要将其包装到 while 循环中(代码是示例,可能无法编译):

.

int left = sizeof(ETHERNET_DIAGNOSTIC_INFO);
char *ptr = rxbuf;
int rd;

while(left>0)
{
rd=recv(sockfd, ptr, left, 0);
if(rd==0)
{
if(left>0) return SOCKET_CLOSED_PREMATURELY;
else return SOCKET_DONE;
} else if(rd==-1 && errno==EAGAIN) {
//do again
continue;
} else if(rd==-1 && errno!=EAGAIN) {
return SOCKET_ERROR;
}
left = left - rd;
ptr=ptr+rd;
}

发送二进制数据的正确方法是使用 protobuf 或 apache thrift,或 ASN 或自己发明一些东西。

关于c++ - 当服务器将数据作为 c 结构发送时,我们可以在客户端将缓冲区类型转换为 C++ 结构吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32618411/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com