使用ASIO实现网络通信时持续返回相同接收数据的原因是什么?
问题根因
asio::read_until执行成功后,只会将匹配到分隔符TRAILER的内容写入传入的缓冲区对象,不会自动清空/消费已经读取完成的有效数据- 你直接调用
buffer.data()获取的永远是缓冲区的起始地址,只要你没有删除已处理的旧数据,后续每次读取拿到的都是第一条消息的内容 - 额外说明:
asio::read_until可能预读取超过当前报文的更多数据到缓冲区中,缓存多条后续报文,属于ASIO的正常优化行为,不是Bug
修复方案
你需要先获取本次读取到的有效字节长度,处理完成后主动消费掉已处理的缓冲区数据,修正后的代码如下:
// read_until返回值为本次读取到的有效字节数(包含结尾的TRAILER) std::size_t read_bytes = asio::read_until(socket, buffer, TRAILER); // 按实际读取长度构造字符串,避免读取到未初始化内容或者残留旧数据 str_data = std::string(asio::buffer_cast<const char*>(buffer.data()), read_bytes); // 消费掉已处理的字节,清空缓冲区中这部分旧数据 buffer.consume(read_bytes);
额外注意点
- 不要直接用
std::string(asio::buffer_cast<const char*>(buffer.data()))构造字符串,该写法依赖字符串结尾的\0,网络报文中不一定携带,会导致读取到脏数据或者内存越界 - 如果
TRAILER是自定义分隔符,需要确认服务端发送的每条报文末尾都正确携带该分隔符,否则read_until会一直阻塞直到超时或者缓冲区满
内容的提问来源于stack exchange,提问作者K-D-G
相关产品推荐
相关产品推荐

