面试题答案
一键面试使用TCP协议实现长连接过程
- 初始化Asio库:
#include <boost/asio.hpp> using boost::asio::io_context; using boost::asio::ip::tcp; io_context io;
- 创建TCP套接字和连接:
tcp::socket socket(io); tcp::resolver resolver(io); tcp::resolver::query query(tcp::v4(), "server_ip", "server_port"); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); boost::asio::connect(socket, endpoint_iterator);
- 数据读写:
- 读操作:
std::array<char, 1024> buffer; socket.async_read_some(boost::asio::buffer(buffer), [&](boost::system::error_code ec, std::size_t length) { if (!ec) { std::string data(buffer.data(), length); // 处理接收到的数据 } });
- 写操作:
std::string message = "Hello, Server!"; boost::asio::async_write(socket, boost::asio::buffer(message), [&](boost::system::error_code ec, std::size_t length) { if (!ec) { // 数据发送成功处理 } });
- 读操作:
处理连接断开重连
- 检测连接断开:在读写操作的回调中,如果
error_code
不为0
,则说明连接可能断开,例如:socket.async_read_some(boost::asio::buffer(buffer), [&](boost::system::error_code ec, std::size_t length) { if (ec) { // 连接断开处理,尝试重连 reconnect(); } });
- 重连实现:
void reconnect() { std::this_thread::sleep_for(std::chrono::seconds(5)); // 等待一段时间再重连 try { tcp::resolver resolver(io); tcp::resolver::query query(tcp::v4(), "server_ip", "server_port"); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); boost::asio::connect(socket, endpoint_iterator); // 重连成功后恢复正常读写操作 } catch (std::exception& e) { // 重连失败处理,可再次尝试或记录日志 } }
心跳检测机制
- 发送心跳包:定期向服务器发送心跳包,例如每10秒发送一次:
void send_heartbeat() { std::string heartbeat = "HEARTBEAT"; boost::asio::async_write(socket, boost::asio::buffer(heartbeat), [&](boost::system::error_code ec, std::size_t length) { if (!ec) { // 心跳包发送成功 } }); std::thread([&]() { while (true) { std::this_thread::sleep_for(std::chrono::seconds(10)); io.post([&]() { send_heartbeat(); }); } }).detach(); }
- 接收心跳包并处理:在接收数据的回调中,判断是否为心跳包,如果是则忽略,例如:
socket.async_read_some(boost::asio::buffer(buffer), [&](boost::system::error_code ec, std::size_t length) { if (!ec) { std::string data(buffer.data(), length); if (data == "HEARTBEAT") { // 心跳包处理,可忽略或记录日志 } else { // 正常数据处理 } } });
性能优化
- 减少内存拷贝:
- 使用
asio::streambuf
进行数据读写,它可以避免多次内存拷贝。例如:boost::asio::streambuf buffer; boost::asio::async_read_until(socket, buffer, '\n', [&](boost::system::error_code ec, std::size_t length) { if (!ec) { std::istream is(&buffer); std::string line; std::getline(is, line); // 处理数据 } });
- 使用
- 优化线程模型:
- 根据实际情况合理使用多线程,例如将
io_context
分配到多个线程中执行任务,提高并发处理能力:std::vector<std::thread> threads; for (std::size_t i = 0; i < std::thread::hardware_concurrency(); ++i) { threads.emplace_back([&io]() { io.run(); }); } for (auto& thread : threads) { thread.join(); }
- 根据实际情况合理使用多线程,例如将
- 启用TCP_NODELAY:禁用Nagle算法,减少数据发送延迟:
socket.set_option(tcp::no_delay(true));
- 连接池复用:如果有多个类似的长连接需求,可以使用连接池复用连接,减少连接创建和销毁的开销。