如何基于boost 1.75.0实现同时监听双端口的boost::asio服务器?
双端口监听的代码调整方案
核心疑问解答
首先明确:你不需要为了双端口监听,在Server类中持有多份socket对象。现有代码里用来做accept中转的成员socket_本身设计上就存在可优化的点,实现多端口监听的核心逻辑是为每一个需要监听的端口,创建独立的、对应绑定端口的acceptor实例,各自跑独立的异步accept循环。
第一步:重构原有Server类
去掉作为accept中转的成员socket,利用Boost.Asio 1.75.0支持的async_accept重载,直接在回调中返回新连接的独立socket,避免成员socket被move后出现状态残留问题:
#include <boost/asio/io_context.hpp> #include <boost/asio/ip/tcp.hpp> #include <iostream> #include "Session.h" using boost::asio::ip::tcp; class Server { public: Server(boost::asio::io_context& io_context, const boost::asio::ip::address& listen_addr, short port) : acceptor_(io_context, tcp::endpoint(listen_addr, port)) { do_accept(); std::cout << "Listening on " << acceptor_.local_endpoint() << "\n"; } private: void do_accept() { // 异步accept直接返回新连接的socket,不需要提前用成员socket中转 acceptor_.async_accept( [this](boost::system::error_code ec, tcp::socket peer_socket) { if (!ec) { std::cout << "Accepted connection from " << peer_socket.remote_endpoint() << "\n"; // 直接将新连接的socket移动给Session管理 std::make_shared<Session>(std::move(peer_socket))->start(); } // 无论本次accept成功或失败,都继续挂下一个accept任务 do_accept(); }); } // 每个Server实例仅持有对应自己监听端口的acceptor即可 tcp::acceptor acceptor_; };
重构后的Server类,单实例就对应一个端口的监听能力,不再依赖成员socket_做中转,彻底消除了move后socket状态不一致的隐患。
第二步:初始化双端口的Server实例
所有监听实例共用同一个全局io_context,在主函数里分别创建对应两个端口的Server对象即可:
int main() { boost::asio::io_context io_context; // 监听127.0.0.1的6500端口 Server server_6500(io_context, boost::asio::ip::make_address("127.0.0.1"), 6500); // 监听127.0.0.1的6600端口 Server server_6600(io_context, boost::asio::ip::make_address("127.0.0.1"), 6600); // 启动全局事件循环,调度所有异步任务 io_context.run(); return 0; }
补充说明
- 现有Session类的构造函数存在语法小问题:初始化列表末尾多了一个逗号,编译时会触发告警或错误,记得删除。
- 如果后续需要扩展监听更多端口,只需要在主函数里新增对应参数的Server实例即可,不需要修改Server类的内部逻辑。
- 所有的连接、定时器、accept任务都共用同一个io_context,不需要为每个端口单独开事件循环,整体资源开销非常低。
内容的提问来源于stack exchange,提问作者yaodav
相关产品推荐
相关产品推荐

