实现现有的网络接口,以相对于C 11中的Endianess定义位字段
Implement existing network interface defining bit-fields with respect to endianess in C++11
我是当前为现有网络远程开发C 11库接口控制文档(ICD)中描述的控制接口。
该接口基于TCP/IPv4,并使用网络字节顺序(aka bigendian )。
要求:应开发库 cross-platform 。
注意:我想使用预处理器开发一个解决方案(AB)。
在对www进行了简短的研究之后,我发现了boost.endian解决与多字节数据类型的Endianess有关的问题。我的方法是如下:
- 通过(多)字节数据类型序列化到流到流STD :: BASIC_OSTREAM ::写,更精确地通过
os.write(reinterpret_cast<char const *>(&kData), sizeof(kData))
。 - 将
std::basic_ostream
转换为std::vector<std::uint8_t>
。 - 通过网络通过boost.asio发送
std::vector<std::uint8_t>
。
到目前为止一切都很好。一切似乎都按预期工作,解决方案应该是平台独立。
现在是棘手的部分:ICD描述了由多个组成的消息单词和一个单词由8位组成。一条消息可以包含多个字段和字段不必与字节调整,这意味着一个单词可以包含多个字段。
示例:请考虑以下消息格式(消息主体开始单词10):
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
等等...
所以现在我需要一个解决方案才能建模并序列化基于位的接口。
我已经看过以下方法:
- 位字段
-
std::bitset
boost::dynamic_bitset
- 1不是跨平台(依赖编译器)。
- 2和3似乎可以与本机字节订单一起使用(即 Little Endian on仅我的计算机),因此使用
boost::dynamic_bitset
的以下示例不为我的场景工作:
代码:
// 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
因此,上面示例中的1024始终序列化为00 04
我的机器上的04 00
。
我真的不知道解决问题的最务实的方法是什么。也许您可以指导我走向正确的方向。
总而言之,我确实需要一个配方来实现现有网络接口定义位与平台无关的字段相对于本机字节顺序库已编译的机器。
最近有人向我指出了一篇关于我汲取灵感的好文章。
std::bitset
具有to_ulong
方法,可用于返回Bitfield的整数表示(Endian Independent),以下代码将以正确的顺序打印您的输出:
#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;
}
请注意,在这种情况下,没有使用位字段的解决方案很容易起作用,因为钻头也将交换在小endian机器上!
例如。在这样的结构中:
struct bits {
unsigned char first_bit:1;
unsigned char rest:7;
};
union {
bits b;
unsigned char raw;
};
将b.fist_bit设置为1将导致1或128的原始值,具体取决于endianness!
hth
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- .cpp和.h文件中的模板专用化声明
- 反向给定链表中的K节点
- 正在查找文档以获得PS4平台的C++中的设备信息
- enum是C++中的宏变量还是整数变量
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 将字符串存储在c++中的稳定内存中
- 文本文件中的单词链表
- 递归函数计算序列中的平方和(并输出过程)
- 如何从C++中的依赖类型中获得它所依赖的类型
- C++中的"inline"关键字
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 用C++中的一个变量定义一个常量
- vector.resize()中的分配错误
- 使用指针从C++中的数组中获取最大值
- arr[-1]在c++中的奇怪行为
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 修复转换 IP 时inet_ntoa中的 Endianess 错误显示反转值
- 实现现有的网络接口,以相对于C 11中的Endianess定义位字段