在 C++11 中反序列化 DNS 数据包对象

Deserializing a DNS packet object in C++11

我有一个 DNS 数据包 class 看起来像这样(我只粘贴了其中的一部分):

class DNSPacket {

public:
    struct DNSHeader {
        unsigned int ID :16; 
        unsigned int QR :1;  
        unsigned int OPCODE :4;  
        unsigned int AA :1;   
        unsigned int TC :1;  
        unsigned int RD :1;    
        unsigned int RA :1;   
        unsigned int Z :3;   

        unsigned int RCODE :4;
        unsigned int QDCOUNT :16;
        unsigned int ANCOUNT :16;
        unsigned int NSCOUNT :16;
        unsigned int ARCOUNT :16;
    };

private:
    DNSHeader header;
    std::vector<DNSQuestion> questions;
    std::vector<DNSAnswer> answers;
    std::vector<DNSAnswer> nameservers; // TODO: DNSAnswer?
    std::vector<DNSAnswer> add_records; // TODO: DNSAnswer?
}

char 数组反序列化为该对象的正确方法是什么?我有的选项是:重载 >> 运算符,添加一个单独的 class 来反序列化它以逐字节读取和反序列化数据读取并使用 reinterpret_cast().

我想在 C++11 中创建一个快速、现代的实现。我应该选择哪种方式?另外,我应该如何反序列化位域 - 我应该坚持按位运算吗?

我的做法是将字 2(第 16 位到第 31 位)视为单个无符号 16 位整数(例如 uint16_t),然后使用按位 AND 简单地获取这些位和 SHIFT 操作。所有其他单词都可以用相同的方式读取,但或多或​​少按原样使用(当然是在从网络字节顺序转换为主机字节顺序之后)。

要将单词 X 作为 uint16_t 您必须进行一些转换:

uint16_t wordX = *reinterpret_cast<uint16_t*>(&your_array[X]);

请注意,对于第二个字,由于它们实际上只是按指定顺序排列的位,因此不会对它们进行字节顺序转换。