实现现有的网络接口,定义关于C ++ 11中的字节序的位字段

时间:2015-05-12 21:39:09

标签: c++ c++11 boost endianness bit-fields

我目前正在为现有网络远程开发C ++ 11库 接口控制文档(ICD)中描述的控制接口。

该接口基于TCP / IPv4并使用网络字节顺序(又名 Big 端)。

要求:图书馆应开发跨平台

注意:我想使用预处理器开发不带(ab)的解决方案。

经过对WWW的简短研究,我发现Boost.Endian解决了这个问题 与多字节数据类型的endianess相关的问题。我的方法是 如下:

  1. 将(多)字节数据类型序列化为流 std::basic_ostream::write,更准确地说是通过 os.write(reinterpret_cast<char const *>(&kData), sizeof(kData))
  2. std::basic_ostream转换为std::vector<std::uint8_t>
  3. 通过网络std::vector<std::uint8_t>发送Word | Bit(s) | Name -----|--------|---------- 10 | 0-2 | a 10 | 3 | b 10 | 4 | c 10 | 5 | d 10 | 6 | e 10 | 7 | RESERVED 11 | 16 | f
  4. 到目前为止一切顺利。一切似乎按预期工作,解决方案应该是 平台独立。

    现在是棘手的部分:ICD描述了由多个组成的消息 单词和一个单词由8位组成。一条消息可以包含多个字段和一个 字段不必是字节对齐的,这意味着一个字可以包含 多个领域。

    示例:考虑以下消息格式(消息正文开头于 10):

    boost::dynamic_bitset

    依旧......

    所以现在我需要一个能够建模和序列化基于位的接口的解决方案。

    到目前为止,我已经研究过以下方法:

    1. Boost.Asio
    2. Bit field
    3. std::bitset

      • boost::dynamic_bitset不是跨平台的(取决于编译器)。
      • 12似乎可以使用原生字节顺序(即 Little Endian 我的机器),所以使用// Using a arithmetic type from the `boost::endian` namespace does not work. using Byte = std::uint8_t; using BitSet = boost::dynamic_bitset<Byte>; BitSet bitSetForA{3, 1}; BitSet bitSetForB{1}; // [...] BitSet bitSetForF{16, 0x400}; // 1024 的以下示例没有 为我的方案工作:
    4. 代码

      00 04

      因此,上面示例中的1024始终序列化为04 00而不是。{   <?php require_once '../db_con.php'; if(!empty($_GET['cat_id'])){ $doc = intval($_GET['cat_id']); try{ $results = $dbh->prepare('SELECT * FROM cat_list WHERE cat_id = ?'); $results->bindParam(1, $doc); $results->execute(); } catch(Exception $e) { echo $e->getMessage(); die(); } $doc = $results->fetch(PDO::FETCH_ASSOC); if($doc == FALSE){ echo '<div class="container">'; echo "<img src='../img/404.jpg' style='margin: 40px auto; display: block;' />"; echo "<h1 style='margin: 40px auto; display: block; text-align: center;' />Oh Crumbs! You upset the bubba!</h1>"; echo '<a href="userList.php" style="margin: 40px auto; display: block; text-align: center;">Get me outta here!</a>'; echo'</div>'; die(); } } ?> 在我的机器上。

      我真的不知道什么是最实用的方法来解决我的问题。 也许你可以引导我走向正确的方向。

      总之,我确实需要一个配方来实现现有的网络接口定义位 字段与平台无关的方式相对于本机字节顺序 已编译库的机器。

1 个答案:

答案 0 :(得分:0)

最近有人向我指出nice article about endianness,我从中获取了灵感。

std::bitset有一个to_ulong方法,可以用来返回位域的整数表示(与endian无关),以下代码将以正确的顺序打印输出:

#include <iostream>
#include <iomanip>
#include <bitset>

int main()
{
  std::bitset<16> flags;
  flags[10] = true;
  unsigned long rawflags = flags.to_ulong();
  std::cout << std::setfill('0') << std::setw(2) << std::hex
            << (rawflags & 0x0FF) // little byte in the beginning                                                     
            << std::setw(2)
            << ((rawflags>>8) & 0x0FF) // big byte in the end                                                         
            << std::endl;
}

请注意,在这种情况下,使用位字段的解决方案不会很容易,因为这些位也会在小端机器上交换!

e.g。在这样的结构中:

struct bits {
  unsigned char first_bit:1;
  unsigned char rest:7;
};
union {
  bits b;
  unsigned char raw;
};

将b.fist_bit设置为1将导致原始值为1或128,具体取决于字节顺序!

HTH