📌 项目地址chriskohlhoff/asio | ⭐ 6,051 颗星 | 🔧 C++ | 📜 未标注

为什么 Asio 是网络编程的基石

C++ 标准库在 C++17 之前没有提供任何网络功能。开发者要么依赖操作系统原生的 socket API(不跨平台且容易出错),要么使用 Boost.Asio(但需要整个 Boost 库)。Asio stand-alone 版本的出现解决了这个痛点:它是一个头文件大部分可用、仅依赖少量系统库的异步 I/O 库,支持 TCP/UDP、串口、POSIX 文件描述符、Windows 管道等,并且可以通过 C++20 协程 实现异步代码的同步化写法。

从代码看 Asio 的用法

1. 定时器 —— 最简单的异步入门

READNE 中的第一个示例展示了一个每 5 秒打印一次的定时器:

#include <asio.hpp>
#include <iostream>

int main() {
  asio::io_context io;
  asio::steady_timer t(io, asio::chrono::seconds{5});
  t.async_wait([](std::error_code ec) {
    std::cout << "Hello, world!" << std::endl;
  });
  io.run();
}

关键点:asio::steady_timerasync_wait 注册一个回调,io.run() 启动事件循环。这是所有异步操作的基础模式:创建 I/O 对象 → 调用 async_* 函数 → io_context.run()

2. TCP 回声服务器

READNE 中给出了一个完整的 TCP 服务器(关键片段):

using asio::ip::tcp;

int main() {
  asio::io_context io;
  tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 12345));
  for (;;) {
    tcp::socket socket(io);
    acceptor.accept(socket);
    char data[1024];
    std::error_code ec;
    std::size_t len = socket.read_some(asio::buffer(data), ec);
    if (!ec) asio::write(socket, asio::buffer(data, len), ec);
  }
}

这是同步阻塞写法。如果需要高并发,换成异步版本(async_acceptasync_read_some、异步回调或协程)。READNE 也提供了异步版本示例,其中使用 async_accept 并递归调用自身来实现循环。

3. 使用 C++20 协程(需要 asio 1.20+)

READNE 展示了使用 co_spawnco_await 的简洁写法:

asio::awaitable<void> echo(tcp::socket socket) {
  char data[1024];
  for (;;) {
    std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable);
    co_await async_write(socket, asio::buffer(data, n), asio::use_awaitable);
  }
}

相比嵌套回调,协程让代码更接近同步编程,但性能并未牺牲。

Asio 的独特设计:Proactor 模式 vs Reactor

大多数异步网络库(如 libuv、libevent)采用 Reactor 模式:系统通知可读/可写事件,应用程序再发起实际的读/写操作。Asio 采用 Proactor 模式:应用程序委托读/写操作给 Asio,操作完成后(数据已在缓冲区中)才通知回调。这意味着:

  • 减少系统调用次数:读操作在数据到达后才触发回调,不必先 poll 再 read。
  • 统一的跨平台模拟:在不需要 I/O 完成端口(如 Linux)的平台上,Asio 用 Reactor 模拟 Proactor,但对外接口不变。
  • 更容易与 Windows 的 IOCP 匹配,因此 Asio 在 Windows 上性能接近原生。

与其他库的对比:
| 特性 | Asio | libuv | Boost.Asio |
|——|——|——-|————|
| 许可证 | Boost 1.0 | MIT | Boost 1.0 |
| 协程支持 | 原生(C++20 或 stackful) | 无 | 原生 |
| 平台覆盖 | 所有主流 + 嵌入式 POSIX | Windows/Linux/macOS | 同 Asio |
| 额外功能 | 串口、SSL(需 OpenSSL) | 文件 I/O、DNS | 同 Asio(但需 Boost) |

选择 Asio 而非 Boost.Asio 的理由:如果你的项目不想引入 Boost 依赖,stand-alone Asio 是轻量级替代。Boost.Asio 实际上就是 Asio 的 Boost 封装版,功能完全一致。

注意事项

  • 许可证:Boost Software License 1.0,宽松开源,允许商用,但需要保留版权声明。
  • 编译要求:C++11 或更高(C++17 更佳),需要链接 pthread(Linux/Unix)或 ws2_32(Windows)。READNE 建议使用 b2 构建系统或直接包含头文件(部分功能需要预编译的 .cpp)。
  • 线程安全io_context 可以被多个线程调用 run(),但同一个 socket 对象上的并发操作通常不安全,除非使用 strand 保证顺序。
  • SSL 支持:不是默认内置,需要额外的 asio/ssl.hpp 并链接 OpenSSL。在 READNE 的示例目录下有 HTTPS 客户端例子。
  • 嵌入式/低内存环境:Asio 性能出色,但事件循环需要少量堆内存(epoll/kevent 等句柄)。对于 tiny C++ 设备也可用,但需留意配置(ASIO_NO_TYPEID 等宏)。

如何获取和开始

项目主页为 chriskohlhoff/asio on GitHub。README 建议直接 git clone 后使用 b2(Boost.Build)编译。最简单的入门方式是复制头文件目录和单独编译 asio.cpp(位于 asio/src/ 下)。具体命令请参考官方 README 的 “Installation” 部分。

这篇文章对你有帮助吗?

发表回复