Boost.Asio读写int向量的服务端客户端程序异常求助
Boost.Asio传输int向量异常:客户端接收随机值且无限阻塞
问题场景
基于Boost.Asio实现服务端与客户端,通过boost::asio::read和boost::asio::write传递int类型vector,预期服务端发送{1,2,3,4,5,6,7,8,9},客户端接收后输出,但实际客户端输出随机值且程序无限运行。
服务端代码(server.cpp)
#include <boost/asio.hpp> #include <vector> using boost::asio::ip::tcp; int main() { boost::asio::io_service ctx; std::vector<int> vc = {1, 2, 3, 4, 5, 6, 7, 8, 9}; tcp::acceptor s(ctx, tcp::endpoint({}, 1234)); tcp::socket conn = s.accept(); boost::asio::write(conn, boost::asio::buffer(vc)); }
客户端代码(client.cpp)
#include <boost/asio.hpp> #include <iostream> using boost::asio::ip::tcp; int main() { boost::asio::io_service ctx; tcp::socket s(ctx); s.connect(tcp::endpoint({}, 1234)); std::vector<int> data(10); boost::asio::read(s, boost::asio::buffer(&data, sizeof(data))); for (auto x : data) { std::cout << x; } }
实际现象
客户端输出大量随机值,且程序无限阻塞无法终止,输出示例:
26710220016661817222889274343557-214234613021914980240162615587848787224662874348677-17396929467224662874344069-204168283435745930074342533275669381911258937235205-10518278365142660544104632-2123472756944701572-531734500513653821913629-431025833424607876961438854961439111-1605430441513807051429161632526724-514957158-1286708961-1722871465961441157961440647-10517823135587861975587910445420122923239035401615725572156135866-921828804-53346303354091785516346447661095676702-529630690162195379954202857416346304291095676702-5296301791134131916325264895177476-53175062851527985158940-514916202558825605-428968316-244381721-1052917621558784836644769668-2041704702-2039585146-244387042-1972796771370310219-227626210-1841446849-244403426-240316597-1972796411370309963-227626210-1841446813-244403426-944959413-244387041-23083408513630013831919857438-1303465186-1536266722-2276098271689063955722665261701735454-46249085116722869991632510750-4814189801664991319558789404-246504676163873306321934878-512852195-508750817540917819-4289364201756172547-164364287-173190433-491957361-18996792912092702721463582721756954624676495360-2143748096148180172812092702759437233-398605863227607747-1588838227121307139359768881-1556233763-1269955807-1049730683-445750395-398606325110167107-1488174931-95114723612151757815976888
问题原因
- Buffer构造错误:客户端中
boost::asio::buffer(&data, sizeof(data))是错误的。sizeof(data)获取的是std::vector对象本身的大小(仅包含内部指针、容量、大小等元数据,固定为几十字节),而非存储int元素的内存总字节数,导致实际读取的字节数远小于预期,后续元素内存未初始化,输出随机值。 - 数据量不匹配:服务端发送9个int的字节数,客户端却尝试读取10个int的字节数,
boost::asio::read是阻塞式读取,必须读取到指定字节数才会返回。服务端发送完毕后退出,客户端无法获取剩余字节,导致程序无限阻塞。
解决方案
方案1:直接修正buffer和数据量匹配
调整客户端代码,让读取的字节数与服务端发送的一致,同时正确构造buffer:
#include <boost/asio.hpp> #include <iostream> using boost::asio::ip::tcp; int main() { boost::asio::io_service ctx; tcp::socket s(ctx); s.connect(tcp::endpoint({}, 1234)); // 服务端发送9个int,创建对应大小的vector std::vector<int> data(9); // 直接传入vector,Asio会自动计算元素总字节数 boost::asio::read(s, boost::asio::buffer(data)); for (auto x : data) { std::cout << x << " "; } std::cout << std::endl; }
方案2:添加长度前缀(更健壮,适合未知数据量场景)
TCP是流协议,没有消息边界,更可靠的方式是先发送数据长度,再发送实际数据,客户端先读取长度再读取对应数据:
修正后的服务端
#include <boost/asio.hpp> #include <vector> #include <cstdint> #include <arpa/inet.h> // 跨平台需替换对应头文件 using boost::asio::ip::tcp; int main() { boost::asio::io_service ctx; std::vector<int> vc = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 发送长度,用uint32_t保证跨平台兼容性 uint32_t size = static_cast<uint32_t>(vc.size()); // 转换为网络字节序(跨平台时必须) size = htonl(size); tcp::acceptor s(ctx, tcp::endpoint({}, 1234)); tcp::socket conn = s.accept(); // 先发送长度 boost::asio::write(conn, boost::asio::buffer(&size, sizeof(size))); // 再发送实际数据 boost::asio::write(conn, boost::asio::buffer(vc)); }
修正后的客户端
#include <boost/asio.hpp> #include <iostream> #include <cstdint> #include <arpa/inet.h> // 跨平台需替换对应头文件 using boost::asio::ip::tcp; int main() { boost::asio::io_service ctx; tcp::socket s(ctx); s.connect(tcp::endpoint({}, 1234)); // 先读取长度 uint32_t size = 0; boost::asio::read(s, boost::asio::buffer(&size, sizeof(size))); // 转换为主机字节序 size = ntohl(size); // 根据长度创建vector std::vector<int> data(size); boost::asio::read(s, boost::asio::buffer(data)); for (auto x : data) { std::cout << x << " "; } std::cout << std::endl; }
内容的提问来源于stack exchange,提问作者NOK
相关产品推荐
相关产品推荐

