Boost.Asio中如何将4字节小端序char数组转换为int长度值
4字节小端序长度字段解析实现
小端序的编码规则为低地址存储数值的低位字节,4字节长度字段中,偏移0位置存数值最低8位,偏移1存次低8位,偏移2存次高8位,偏移3存最高8位。以下实现均不依赖本机字节序,跨平台运行安全。
方案1:手动位运算实现(无额外依赖)
直接逐字节做位运算拼接,没有第三方依赖,也不会触发内存对齐问题:
#include <cstdint> // 固定解析4字节小端数据为32位无符号整数 uint32_t le4bytes_to_uint32(const char* buf) { return (static_cast<uint32_t>(static_cast<unsigned char>(buf[0])) << 0) | (static_cast<uint32_t>(static_cast<unsigned char>(buf[1])) << 8) | (static_cast<uint32_t>(static_cast<unsigned char>(buf[2])) << 16) | (static_cast<uint32_t>(static_cast<unsigned char>(buf[3])) << 24); }
针对你给出的示例:如果收到的4字节长度段是\x00\x00\x00\x48(字符H的ASCII值为0x48),按小端规则解析结果为0x48000000(十进制1207959552);如果预期解析结果为72,对应实际收到的小端字节序列应为\x48\x00\x00\x00,注意核对收发端的字节顺序。
方案2:使用现有工具库实现(适配你当前的Boost技术栈)
你已经在使用Boost.Asio,可直接调用库内置的字节序转换接口,不用自行实现位运算:
#include <cstring> #include <cstdint> #include <boost/endian/conversion.hpp> uint32_t converted_int = 0; std::memcpy(&converted_int, buffer_size, 4); // 小端字节序转当前主机字节序 converted_int = boost::endian::little_to_native(converted_int);
原有代码的问题修正
你的原始代码有两个易触发故障的问题,需要同步调整:
- 第二个
receive调用传入的缓冲区和长度参数错误,应该传入后续报文的缓冲区,长度为解析出的载荷长度 - 标准C++不支持栈上变长数组(
char buffer_obj[converted_int]属于编译器非标准扩展),载荷长度较大时会直接触发栈溢出,建议用std::vector<char>在堆上分配存储
修正后的完整参考代码:
#include <cstdint> #include <vector> #include <boost/asio.hpp> constexpr int SIZE_DESC = 4; // 长度字段固定为4字节 char buffer_size[SIZE_DESC]; // 注意校验接收返回值,处理连接断开、收不足字节的异常 size_t recv_len = m_socket->receive(boost::asio::buffer(buffer_size, SIZE_DESC)); if (recv_len != SIZE_DESC) { // 自定义异常处理逻辑 } uint32_t payload_len = le4bytes_to_uint32(buffer_size); std::vector<char> buffer_obj(payload_len); recv_len = m_socket->receive(boost::asio::buffer(buffer_obj.data(), payload_len)); if (recv_len != payload_len) { // 自定义报文截断异常处理逻辑 } // 后续直接处理buffer_obj中存储的序列化对象即可
注意:不要直接用指针强转的方式(如
*(int*)buffer_size)读取值,该写法依赖本机字节序,在大端架构设备(部分ARM、PowerPC服务器)上会直接解析错误,还可能因为内存对齐问题触发程序崩溃。
内容的提问来源于stack exchange,提问作者Michael WS
相关产品推荐
相关产品推荐

