使用Boost Asio的Scatter/Gather IO发送含vector结构体收不全数据如何解决
问题核心错误点
你代码里存在多个底层逻辑错误,是导致接收不完整、阻塞的根本原因:
- 服务端发送缓冲区逻辑完全错误
std::vector本身是包含三个指针的内部管理结构体,sizeof(filePacket_.values)拿到的是这个管理结构体的固定大小(64位环境下通常24字节),完全不是vector内存储的实际数据长度。你直接给ba::buffer传&filePacket_.values相当于把vector的管理结构体内存发出去了,没有发送真正存在堆上的二进制数据。
正确写法是直接传vector实例:ba::buffer(filePacket_.values),Asio会自动取vector存储的实际数据地址和长度。 - 服务端未对
filePacketSize_赋值
你仅在processData中填充了filePacket_的val和values成员,完全没有计算总长度赋值给filePacketSize_,导致发送的大小字段是栈上的随机脏值,客户端拿到的responseSize本身就是错的。
正确写法是在processData末尾补充:filePacketSize_ = sizeof(filePacket_.val) + filePacket_.values.size(); - 服务端
processData存在编译错误
代码行processedData.values.push_back(dist(re));错误使用了类型名processedData,应该改为访问成员变量filePacket_.values.push_back(dist(re)); - 客户端接收逻辑错误
processedData结构体根本没有size成员,你代码中ba::buffer(&response.size, sizeof(uint16_t))属于越界访问,会直接改写内存造成未定义行为。你已经单独读取了responseSize,不需要重复读取大小字段。- 接收vector数据的逻辑同样错误,不能直接取vector的地址,需要先给vector扩容到预期长度,再传入Asio的buffer:
processedData response {}; // 先读val字段 ba::read(socket, ba::buffer(&response.val, sizeof(uint8_t))); // 给vector预留足够空间 response.values.resize(responseSize - sizeof(uint8_t)); // 读vector的实际数据 ba::read(socket, ba::buffer(response.values));
- 额外注意:结构体对齐问题
直接对自定义结构体做内存拷贝收发,可能因为不同编译器的对齐规则产生填充字节,建议给跨进程传输的结构体加__attribute__((packed))(GCC/Clang)或者#pragma pack(MSVC)修饰,避免字节错位。
修正后核心逻辑参考
服务端发送部分
// processData 末尾补充 filePacketSize_ = sizeof(filePacket_.val) + filePacket_.values.size(); // 构造发送缓冲区修改为 std::vector<ba::const_buffer> msg { ba::buffer(&filePacketSize_, sizeof(uint16_t)), ba::buffer(&filePacket_.val, sizeof(filePacket_.val)), ba::buffer(filePacket_.values) };
客户端接收部分
uint16_t responseSize {}; ba::read(socket, ba::buffer(&responseSize, sizeof(uint16_t))); processedData response {}; // 读val字段 ba::read(socket, ba::buffer(&response.val, sizeof(uint8_t))); // 扩容vector后读数据 response.values.resize(responseSize - sizeof(uint8_t)); ba::read(socket, ba::buffer(response.values));
内容的提问来源于stack exchange,提问作者Spiwocoal
相关产品推荐
相关产品推荐

