2015-09-04 38 views
0

我有一個DNS數據包類,看起來像這樣(我粘貼只是其中的一部分):反序列化一個DNS包對象在C++ 11

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的正確方法數組到這個對象?我有的選項是:重載>>運算符,添加一個單獨的類以反序列化它以讀取並反序列化字節後的數據讀取字節並使用reinterpret_cast()

我想在C++ 11中創建一個快速,現代的實現。我應該選擇哪種方式?另外,我應該如何反序列化位域 - 我應該堅持按位運算嗎?

+1

char數組的格式是什麼? – Surt

+0

這是一個封裝了一些(問題或答案)DNS數據包的UDP數據幀。 – syntagma

+0

您的結構是錯誤的,根據[this](http://www.comptechdoc.org/independent/networking/terms/dns-message-format.html),「Z」字段是三位。 –

回答

1

我會這樣做的方式是將字2(位16至31)視爲單個無符號的16位整數(例如uint16_t),並通過使用按位AND和SHIFT操作來簡單地獲取位。所有其他字都可以用相同的方式讀取,但是按原樣使用或多或少(當然,從網絡字節順序轉換爲主機字節順序後)。

爲了讓字X字作爲uint16_t你必須做一些鑄造:

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

注意,對於第二個字,因爲他們真的只是位,他們是按照指定的順序,沒有字節順序轉換在他們身上完成。

+0

endianness怎麼樣? Thete並沒有說明他正在從事哪個平臺。 – marom

+0

@marom除非RFC另有說明,否則長度超過8位的字應始終採用網絡字節順序,無論協議如何。 –

+0

這對於來自網絡的數據來說是正確的,但是現在的大多數平臺都是小端的,所以對於16位字應該有字節反轉。 uint16_t wordX =(your_array [X] << 8)+ your_array [X + 1] – marom