Boost.Asio — 异步 I/O
Boost.Asio 是 C++ 异步网络编程的事实标准,也是 C++ 网络 TS 的基础。支持 TCP/UDP/串口/定时器,配合协程极其强大。
安装
bash
# vcpkg(独立 asio,不依赖 Boost)
vcpkg install asio
# 或者完整 Boost
vcpkg install boost-asio
# CMake
find_package(Boost REQUIRED COMPONENTS system)
target_link_libraries(myapp PRIVATE Boost::system)
# 或独立 asio
find_package(asio REQUIRED)
target_link_libraries(myapp PRIVATE asio::asio)核心概念
io_context — 事件循环,驱动所有异步操作
executor — 决定回调在哪里执行
strand — 串行化执行,避免并发回调
socket — TCP/UDP 套接字
acceptor — TCP 服务端监听
resolver — DNS 解析
timer — 定时器
buffer — 数据缓冲区TCP 服务端
cpp
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
tcp::socket socket_;
std::array<char, 4096> buf_;
public:
explicit 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(asio::buffer(buf_),
[this, self](boost::system::error_code ec, size_t n) {
if (!ec) {
do_write(n);
}
});
}
void do_write(size_t n) {
auto self = shared_from_this();
asio::async_write(socket_, asio::buffer(buf_, n),
[this, self](boost::system::error_code ec, size_t) {
if (!ec) {
do_read(); // 继续读
}
});
}
};
class Server {
tcp::acceptor acceptor_;
public:
Server(asio::io_context& io, uint16_t port)
: acceptor_(io, 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) {
std::make_shared<Session>(std::move(socket))->start();
}
do_accept(); // 继续接受连接
});
}
};
int main() {
asio::io_context io;
Server server(io, 8080);
std::cout << "服务器启动,端口 8080\n";
io.run(); // 事件循环
}TCP 客户端
cpp
#include <boost/asio.hpp>
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
int main() {
asio::io_context io;
tcp::resolver resolver(io);
tcp::socket socket(io);
// 同步连接
auto endpoints = resolver.resolve("example.com", "80");
asio::connect(socket, endpoints);
// 发送 HTTP 请求
std::string request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
asio::write(socket, asio::buffer(request));
// 读取响应
boost::system::error_code ec;
std::string response;
asio::read_until(socket, asio::dynamic_buffer(response), "\r\n\r\n", ec);
std::cout << response << "\n";
}协程风格(C++20,推荐)
cpp
#include <boost/asio.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/detached.hpp>
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
// 协程 echo 服务端
asio::awaitable<void> handle_client(tcp::socket socket) {
try {
std::array<char, 4096> buf;
while (true) {
size_t n = co_await socket.async_read_some(
asio::buffer(buf), asio::use_awaitable);
co_await asio::async_write(
socket, asio::buffer(buf, n), asio::use_awaitable);
}
} catch (const std::exception& e) {
// 连接断开
}
}
asio::awaitable<void> listener(uint16_t port) {
auto executor = co_await asio::this_coro::executor;
tcp::acceptor acceptor(executor, {tcp::v4(), port});
while (true) {
tcp::socket socket = co_await acceptor.async_accept(asio::use_awaitable);
asio::co_spawn(executor, handle_client(std::move(socket)), asio::detached);
}
}
int main() {
asio::io_context io;
asio::co_spawn(io, listener(8080), asio::detached);
io.run();
}定时器
cpp
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
namespace asio = boost::asio;
int main() {
asio::io_context io;
// 一次性定时器
asio::steady_timer timer(io, std::chrono::seconds(3));
timer.async_wait([](boost::system::error_code ec) {
if (!ec) std::cout << "3秒后触发\n";
});
// 周期定时器(协程风格)
asio::co_spawn(io, [&]() -> asio::awaitable<void> {
asio::steady_timer t(co_await asio::this_coro::executor);
while (true) {
t.expires_after(std::chrono::seconds(1));
co_await t.async_wait(asio::use_awaitable);
std::cout << "每秒触发\n";
}
}, asio::detached);
io.run();
}多线程 io_context
cpp
#include <boost/asio.hpp>
#include <thread>
#include <vector>
namespace asio = boost::asio;
int main() {
asio::io_context io;
// 防止 io_context 在没有任务时退出
auto work = asio::make_work_guard(io);
// 多线程运行事件循环
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) {
threads.emplace_back([&io] { io.run(); });
}
// strand:确保回调串行执行(避免并发问题)
asio::strand<asio::io_context::executor_type> strand(io.get_executor());
asio::post(strand, [] { std::cout << "串行任务 1\n"; });
asio::post(strand, [] { std::cout << "串行任务 2\n"; });
// 两个任务不会并发执行
work.reset(); // 允许 io_context 退出
for (auto& t : threads) t.join();
}关键认知
Boost.Asio 的核心是Proactor 模式:发起异步操作,操作完成时回调。协程风格(co_await)让异步代码的可读性接近同步代码,是现代 Asio 的推荐用法。多线程时用 strand 串行化回调,避免数据竞争。