gpt4 book ai didi

c - 在 C 中通过 TCP (SOCK_STREAM) 套接字传递结构

转载 作者:可可西里 更新时间:2023-11-01 02:30:33 25 4
gpt4 key购买 nike

我有一个小型客户端服务器应用程序,我希望在其中使用 C 而不是 C++ 通过 TCP 套接字发送整个结构。假设结构如下:

    struct something{
int a;
char b[64];
float c;
}

我发现很多帖子说我需要使用 pragma pack 或在发送和接收之前序列化数据。

我的问题是,使用 JUST pragma pack 还是仅仅使用 serialzation 就足够了吗?还是我需要同时使用两者?

此外,由于序列化是处理器密集型过程,这会使您的性能急剧下降,那么在不使用外部库的情况下序列化结构的最佳方法是什么(我想要示例代码/算法)?

最佳答案

您需要以下内容才能通过网络可移植地发送结构:

  • 打包结构。对于 gcc 和兼容的编译器,使用 __attribute__((packed)) 执行此操作。

  • 除了固定大小的无符号整数、满足这些要求的其他压缩结构或任何前者的数组之外,不要使用任何成员。有符号整数也可以,除非您的机器不使用二进制补码表示。

  • 决定您的协议(protocol)是使用小端还是大端整数编码。在读取和写入这些整数时进行转换。

  • 此外,不要采用压缩结构成员的指针,大​​小为 1 或其他嵌套压缩结构的指针除外。参见 this answer .

编码和解码的简单示例如下。它假定字节顺序转换函数 hton8()ntoh8()hton32()ntoh32() 可用(前两个是空操作,但为了保持一致性)。

#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>

// get byte order conversion functions
#include "byteorder.h"

struct packet {
uint8_t x;
uint32_t y;
} __attribute__((packed));

static void decode_packet (uint8_t *recv_data, size_t recv_len)
{
// check size
if (recv_len < sizeof(struct packet)) {
fprintf(stderr, "received too little!");
return;
}

// make pointer
struct packet *recv_packet = (struct packet *)recv_data;

// fix byte order
uint8_t x = ntoh8(recv_packet->x);
uint32_t y = ntoh32(recv_packet->y);

printf("Decoded: x=%"PRIu8" y=%"PRIu32"\n", x, y);
}

int main (int argc, char *argv[])
{
// build packet
struct packet p;
p.x = hton8(17);
p.y = hton32(2924);

// send packet over link....
// on the other end, get some data (recv_data, recv_len) to decode:
uint8_t *recv_data = (uint8_t *)&p;
size_t recv_len = sizeof(p);

// now decode
decode_packet(recv_data, recv_len);

return 0;
}

就字节序转换函数而言,你系统的htons()/ntohs()htonl()/ntohl() 可用于分别将 16 位和 32 位整数转换为大端或从大端转换。但是,我不知道有任何用于 64 位整数的标准函数,或者与 little endian 之间的转换。您可以使用 my byte order conversion functions ;如果这样做,您必须通过定义 BADVPN_LITTLE_ENDIANBADVPN_BIG_ENDIAN 告诉它您机器的字节顺序。

就带符号整数而言,转换函数可以像我编写和链接的方法一样安全地实现(直接交换字节);只需将未签名更改为已签名即可。

更新:如果你想要一个高效的二进制协议(protocol),但不喜欢摆弄字节,你可以尝试像Protocol Buffers这样的东西。 (C implementation)。这允许您在单独的文件中描述消息的格式,并生成用于编码和解码指定格式的消息的源代码。我自己也实现了类似的东西,但大大简化了;见my BProto generatorsome examples (查看 .bproto 文件和 addr.h 以获取使用示例)。

关于c - 在 C 中通过 TCP (SOCK_STREAM) 套接字传递结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8000851/

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