0

バイトの順序に関係なく、バイト配列から構築できる IPv4 ヘッダー構造を表す次の c++11 クラスを検討してください。

#include <arpa/inet.h>
#include <netinet/in.h>

namespace Net {
  using addr_t = ::in_addr_t;
  #pragma pack(push, 1)
  struct ip_header_t {
    uint8_t  ver_ihl;
    uint8_t  tos;
    uint16_t total_length;
    uint16_t id;
    uint16_t flags_fo;
    uint8_t  ttl;
    uint8_t  protocol;
    uint16_t checksum;
    addr_t   src_addr;
    addr_t   dst_addr;

    ip_header_t( const uint8_t* bytes, const bool ntoh = false ) {
      auto o = (ip_header_t&)*bytes;
      ver_ihl      = o.ver_ihl;
      tos          = o.tos;
      ttl          = o.ttl;
      protocol     = o.protocol;
      total_length = ntoh? ntohs(o.total_length) : o.total_length;
      id           = ntoh? ntohs(o.id) : o.id;
      flags_fo     = ntoh? ntohs(o.flags_fo) : o.flags_fo;
      checksum     = ntoh? ntohs(o.checksum) : o.checksum;
      src_addr     = ntoh? ntohl(o.src_addr) : o.src_addr;
      dst_addr     = ntoh? ntohl(o.dst_addr) : o.dst_addr;
    };
  };
  #pragma pack(pop)
}

バイト配列を受け入れることが、これを行うための最も安全な、または最も意味的に正しい方法ではない可能性があることを懸念しています。構造自体として配列をキャストすることは、型の安全性を欠く非常に C っぽいメソッドのように思えます (境界チェックは言うまでもありません)。呼び出し元にそれについて心配させ、インスタンスへの const 参照を要求する方がよいでしょうか?

4

3 に答える 3

0

バイト配列をこのクラスにキャストすることは、間違いなく正しいことではありません。前述のように、システムごとにバイト順が異なる可能性があります(ntohsコンストラクターに があるのはそのためです)。

クラスを配置する場所は、エンティティの役割と責任に完全に依存します。デザインを見ないとなんとも言えません。

于 2013-04-03T18:36:09.077 に答える
0

最善の解決策は、バイト オーダー変換を処理できるコピー コンストラクターを提供し、呼び出し元がキャストを行うことに依存することだと私には思えます。

そのようです:

/* copy constructor: */
ip_header_t( const ip_header_t& src, const bool ntoh = false )
  : ver_ihl(src.ver_ihl),
    tos(src.tos),
    ttl(src.ttl),
    protocol(src.protocol) {
  total_length = ntoh? ntohs(src.total_length) : src.total_length;
  id           = ntoh? ntohs(src.id)           : src.id;
  flags_fo     = ntoh? ntohs(src.flags_fo)     : src.flags_fo;
  checksum     = ntoh? ntohs(src.checksum)     : src.checksum;
  src_addr     = ntoh? ntohl(src.src_addr)     : src.src_addr;
  dst_addr     = ntoh? ntohl(src.dst_addr)     : src.dst_addr;
};

/* client code using byte array in network-order */
auto ip_header = Net::ip_header_t((Net::ip_header_t&)*(byte_array), true);

私も、このソリューションが一番気に入っていると 100% 確信しているわけではありません。バイト順のスワッピングがオブジェクトの構築に厳密に関連していないことを考えると、これを行う非メンバー関数を作成する方が良いかもしれません。また、フィールドのアラインメントと順序付けに関与することは、クラスの正当な責任ではないかもしれません。

于 2013-04-08T21:23:47.070 に答える