这正是 Boost.Asio 最擅长的地方!它把 Linux 的 epoll 和 Windows 的 IOCP 封装成了统一的接口,让你完全不用写 #ifdef _WIN32 这种宏来区分平台。
下面我为你展示如何用 C++17 + Boost.Asio 实现一个标准的、跨平台的异步 TCP 服务器。
🛠️ 第一步:环境准备
在写代码之前,你需要确保安装了 Boost 库。
-
Ubuntu/Linux:
bashsudo apt-get install libboost-all-dev -
Windows (使用 vcpkg):
bashvcpkg install boost-asio
💻 第二步:核心代码实现
这是一个基于 Reactor 模式 的服务器,支持高并发,且代码在 Windows 和 Linux 上完全通用。
cpp
#include <iostream>
#include <vector>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
// 1. 会话类:负责处理单个客户端的连接
class Session : public enable_shared_from_this<Session> {
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
public:
Session(tcp::socket socket) : socket_(std::move(socket)) {}
void start() {
do_read();
}
private:
void do_read() {
// 异步读取:不阻塞线程
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
// 读取成功,异步回写
do_write(length);
}
});
}
void do_write(std::size_t length) {
auto self(shared_from_this());
boost::asio::async_write(
socket_, boost::asio::buffer(data_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/) {
if (!ec) {
// 写完后继续读
do_read();
}
});
}
};
// 2. 服务器类:负责监听端口和接受连接
class TcpServer {
boost::asio::io_context& io_context_;
tcp::acceptor acceptor_;
public:
TcpServer(boost::asio::io_context& io_context, short port)
: io_context_(io_context),
acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}
private:
void do_accept() {
// 异步接受新连接
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket) {
if (!ec) {
// 创建会话对象并开始处理
make_shared<Session>(std::move(socket))->start();
cout << "New client connected" << endl;
}
// 继续接受下一个连接
do_accept();
});
}
};
int main() {
try {
// 1. 创建 io_context (核心事件循环)
boost::asio::io_context io_context;
// 2. 启动服务器
TcpServer server(io_context, 12345);
cout << "Server running on port 12345..." << endl;
// 3. 启动多线程池 (模拟多线程处理)
// 在 Windows 下底层是 IOCP,Linux 下是 epoll
vector<thread> threads;
for (int i = 0; i < 4; ++i) {
threads.emplace_back([&io_context]() {
io_context.run();
});
}
// 等待所有线程结束
for (auto& t : threads) {
t.join();
}
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
📝 第三步:编译与运行
Linux (g++)
bash
g++ -std=c++17 server.cpp -o server -lboost_system -pthread
./server
Windows (CMake + vcpkg)
如果你使用 CMake,CMakeLists.txt 非常简单:
cmake
cmake_minimum_required(VERSION 3.10)
project(TcpServer)
set(CMAKE_CXX_STANDARD 17)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(server server.cpp)
target_link_libraries(server PRIVATE Boost::system)
🔍 为什么它能跨平台?(核心原理)
Boost.Asio 的魔法在于它封装了底层的差异:
| 层面 | Linux 底层 | Windows 底层 | Boost.Asio 封装 |
|---|---|---|---|
| I/O 多路复用 | epoll |
IOCP (完成端口) |
boost::asio::io_context |
| Socket 句柄 | int (文件描述符) |
SOCKET (句柄) |
boost::asio::ip::tcp::socket |
| 错误码 | errno |
WSAGetLastError() |
boost::system::error_code |
| 启动/关闭 | 无特殊操作 | WSAStartup / WSACleanup |
自动处理 (无需手动调用) |
🌟 代码亮点解析
-
boost::asio::io_context:这是整个库的心脏。在 Linux 上,调用
io_context.run()时,它内部会去epoll_wait;在 Windows 上,它会去GetQueuedCompletionStatus(IOCP)。你完全不用关心底层。 -
enable_shared_from_this:在
Session类中,我们使用了shared_from_this()。这是为了防止异步操作(如async_read)还在进行时,Session对象被意外销毁。这是一种非常安全的内存管理方式。 -
多线程模型 :
代码最后启动了 4 个线程运行
io_context.run()。- Linux 下 :这 4 个线程会同时抢锁处理
epoll返回的就绪事件。 - Windows 下:这 4 个线程会作为 IOCP 的工作线程池,自动负载均衡。
- Linux 下 :这 4 个线程会同时抢锁处理
🚀 总结
使用 Boost.Asio,你只需要关注业务逻辑 (怎么读、怎么写),而不用关心系统调用(怎么监听、怎么轮询)。这就是它成为 C++ 网络编程事实标准的原因。