3

让我们假设以下内容:

我想为UDP 数据包创建一个结构。每个帧通常由以太网头、IP 头、UDP 头和可选的有效载荷组成,最后是 FCS(帧校验和序列)。
有效载荷长度未知/灵活。这意味着在创建结构时,有效负载必须是它的最后一个成员(灵活数组成员)。因此,FCS 没有立足之地。

所以我想到了还有哪些可能性。

我想出了以下代码:

#define UDP_PKT(name, payload_length) struct __attribute((__packed__))      \
    {                                                                       \
        struct ether_header eth;                                            \
        struct ip iph;                                                      \
        struct udphdr udph;                                                 \
        unsigned char payload[payload_length];                              \
        u_int32_t fcs;                                                      \
    } name;

因为这是不允许的:

struct __attribute__((__packed__)) udp_packet
{
    struct ether_header eth;
    struct ip iph;
    struct udphdr udph;
    unsigned char payload[]; // fam, must always be the last member
    u_int32_t fcs;
};

我的问题:这是我必须在结构中包含 FCS 而没有固定数组(有效负载)大小的唯一可能性吗?

如果是这样,这是一个好的解决方案吗?这被认为是好的做法吗?

4

2 回答 2

4

具有灵活数组成员的大小struct在运行时确定,因此您的第一种方法也不起作用。解决方案是在您准备好序列化您struct的线路时将 FCS 放在缓冲区的末尾:

struct __attribute__((__packed__)) udp_packet {
    struct ether_header eth;
    struct ip iph;
    struct udphdr udph;
    u_int32_t fcs;
    unsigned char payload[]; // Move fcs up
};

void serialize_udp_packet(const udp_packet* p) {
    // Compute buffer size, and allocate the buffer
    // Place the header into the buffer
    // Copy the payload into the buffer
    // Place FCS into the buffer at the end
}

您甚至可以完全排除fcsudp_packet仅在序列化struct. 这种方法的一个优点是您可以自由地改变有效负载,而不必一直同步FCS到已更改的有效负载。

于 2018-12-14T20:15:15.650 回答
0

为有效负载和校验和分配内存。使用指针访问校验和。简单高效

于 2018-12-14T20:23:24.707 回答