boost::asio如何实现客户端发字符串、服务端排序返回及空值问题修复
问题核心原因
- 异步操作执行逻辑错误:你在
start方法里同时发起了异步读和异步写操作,boost.asio的异步接口是立即返回的,不会等待IO完成,此时写操作大概率会在读操作完成前执行,data还未收到客户端发送的内容,自然返回空字符串。 - 读操作后未限定处理范围:
handle_read里直接对整个data容器排序,没有限定仅处理bytes_transferred长度的实际接收内容,未初始化/未读到的无效内容也会参与排序,同时如果data是char数组还会缺失字符串结束符。 - 缺少异常判断:
handle_read里没有判断读操作是否出错,也没处理接收长度为0的边界情况。
修复后的代码
void start() { // 仅先发起异步读,读完成后再触发写操作 sock.async_read_some( boost::asio::buffer(data), boost::bind(&con_handler::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handle_read(const boost::system::error_code& err, size_t bytes_transferred) { if (err) { std::cerr << "read error: " << err.message() << std::endl; sock.close(); return; } if (bytes_transferred == 0) { sock.close(); return; } // 仅排序实际收到的字节范围 std::sort(data.begin(), data.begin() + bytes_transferred); // 如果data是char数组,需要补字符串结束符方便后续打印 // data[bytes_transferred] = '\0'; // 读完成、排序完成后再发起异步写 sock.async_write_some( // 只写排序后的实际长度内容 boost::asio::buffer(data, bytes_transferred), boost::bind(&con_handler::handle_write, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handle_write(const boost::system::error_code& err, size_t bytes_transferred) { if (!err) { std::cout<<"server side: "<<data<<std::endl; } else { std::cerr << "write error: " << err.message() << std::endl; sock.close(); } }
关键改动说明
- 调整异步操作顺序:
start方法仅发起异步读,读操作完成且排序结束后,再在handle_read里发起异步写,保证写的是已经处理好的内容。 - 限定处理和发送的长度:排序仅针对实际收到的
bytes_transferred长度的内容,写操作也仅发送对应长度,避免无效内容混入。 - 补充读操作的异常和边界判断,避免无效操作。
可选优化:如果要保证完整接收客户端发送的整行/定长字符串,建议使用boost::asio::async_read替代async_read_some,后者可能只接收到部分数据就触发回调,需要自行处理粘包问题。
内容的提问来源于stack exchange,提问作者user2515165
相关产品推荐
相关产品推荐

