跳到主要内容Asio C++库核心特性与基础编程模型详解 | 极客日志C++
Asio C++库核心特性与基础编程模型详解
Asio 是跨平台 C++ 异步 I/O 库,基于 Boost 或独立分发。核心特性包括多范式异步模型、全面网络功能、高精度定时器及串口通信支持。它利用操作系统底层机制如 epoll、IOCP 实现高性能并发。提供 Boost.Asio 与 Standalone Asio 两种版本,API 兼容。基本编程模型围绕 io_context 事件循环展开,包含创建上下文、I/O 对象、启动异步操作、运行事件循环及处理结果五个步骤。示例展示了 TCP 回声服务器的实现,涵盖 Session 类管理与 Server 类监听逻辑。安装可通过源码编译或包管理器完成,适用于高并发网络服务开发。
观心4 浏览 什么是 Asio C++库?
Asio(Asynchronous I/O 的缩写)是一个专为网络和低级 I/O 编程设计的跨平台 C++ 库,其核心目标是提供一套一致、高效的异步编程模型,帮助开发者构建高性能、可扩展的并发应用程序。该库由澳大利亚软件工程师 Christopher M. Kohlhoff 于 2003 年首次开发,最初作为独立项目发布,2005 年正式纳入 Boost 库生态系统(成为 Boost.Asio),此后逐渐成为 C++ 异步编程领域的事实标准之一。如今,Asio 不仅是 Boost 库的核心组件,还提供独立分发版本(Standalone Asio),开发者可根据项目需求选择是否依赖 Boost 生态。
在计算机科学领域,I/O 操作(尤其是网络 I/O)往往是应用程序性能的瓶颈。传统同步 I/O 模型中,一个线程对应一个 I/O 操作,当操作未完成时线程会处于阻塞状态,导致系统资源(线程、内存)被大量占用,难以应对高并发场景(如万级以上网络连接)。Asio 的出现正是为了解决这一痛点——它基于操作系统底层的异步 I/O 机制(如 Linux 的 epoll、Windows 的 IOCP、macOS 的 kqueue),通过'事件驱动'模式实现单线程(或少量线程)处理大量并发 I/O 操作,从根本上避免了线程创建、上下文切换的开销,同时简化了并发逻辑的开发难度。
值得注意的是,Asio 并非仅面向网络编程,其设计理念是'将所有 I/O 操作抽象为异步事件',因此除了 TCP/UDP 等网络功能,还支持串口通信、定时器、信号处理等低级 I/O 场景,形成了一套统一的异步编程范式。
Asio 的核心特性
Asio 的强大之处在于其精心设计的核心特性,这些特性既满足了高性能需求,又兼顾了开发效率和跨平台兼容性:
1. 多范式的异步模型
Asio 支持三种主流的异步编程范式,开发者可根据项目复杂度和团队习惯灵活选择:
- 回调函数(Callback-based):最基础的异步模式,通过传递函数对象(如
std::function、lambda 表达式)作为操作完成后的处理逻辑。适用于简单场景,代码直观但嵌套较深时易出现'回调地狱'(Callback Hell)。
- Future/Promise:基于 C++11 标准的
std::future 和 std::promise,将异步操作的结果封装为'未来值',通过 get() 方法阻塞获取结果或 wait_for() 非阻塞检查状态。适用于需要同步等待结果的场景,代码线性度优于回调。
- 协程(Coroutine):支持 C++20 标准协程(通过
co_await、co_return 关键字),可将异步代码写成'同步风格',彻底消除回调嵌套,同时保持异步的高效性。这是 Asio 推荐的高级模式,也是现代 C++ 异步编程的发展方向。
2. 全面的网络功能
Asio 提供了对主流网络协议的完整支持,且接口设计符合 POSIX 套接字习惯,降低了开发者的学习成本:
- TCP 协议:支持客户端(
ip::tcp::socket)和服务器(ip::tcp::acceptor)开发,包含连接建立、数据收发、连接关闭等全流程操作,支持 IPv4 和 IPv6 双栈。
- UDP 协议:通过
ip::udp::socket 实现无连接的数据报通信,支持广播、多播(Multicast)等高级特性,适用于低延迟、高吞吐量的场景(如实时音视频、游戏)。
- ICMP 协议:支持 ICMP 消息(如 ping 请求)的发送和接收,可用于网络连通性检测工具开发。
- 其他特性:支持域名解析(
ip::tcp::resolver)、SSL/TLS 加密(需结合 Boost.SSL 或 OpenSSL)、Socket 选项配置(如 SO_REUSEADDR、TCP_NODELAY)等。
3. 高精度定时器
定时器是异步编程中的核心组件,Asio 提供了三种定时器类型,满足不同时间精度和使用场景:
steady_timer:基于'稳定时钟'(Steady Clock),时钟频率不受系统时间调整影响(如用户修改系统时间、NTP 同步),适用于需要精确间隔的场景(如定时任务、超时控制)。
system_timer:基于'系统时钟'(System Clock),时钟时间与系统当前时间一致,适用于需要与系统时间关联的场景(如定时在每天凌晨执行任务)。
high_resolution_timer:基于'高精度时钟'(High-resolution Clock),提供最高精度的时间测量(通常可达纳秒级),适用于对时间精度要求极高的场景(如性能基准测试)。所有定时器均支持异步等待(async_wait),并可通过 cancel() 方法取消未触发的定时任务,灵活性极高。
4. 串行端口通信
Asio 对串行端口(Serial Port)的支持覆盖了主流操作系统,提供了与网络 Socket 一致的异步编程接口,简化了跨平台串口应用的开发:
- 支持 Windows 的 COM 口、Linux/macOS 的
/dev/tty 设备。
- 可配置串口参数:波特率(Baud Rate)、数据位(Data Bits)、停止位(Stop Bits)、校验位(Parity)、流控制(Flow Control)等。
- 支持异步读写操作,可用于嵌入式设备通信、工业控制(如 PLC)、硬件调试等场景。
5. 操作系统信号处理
Asio 允许开发者以异步方式处理操作系统信号(如 SIGINT、SIGTERM),避免了传统信号处理函数的局限性(如不可重入、只能调用有限函数):
- 通过
signal_set 类注册需要监听的信号。
- 当信号触发时,异步调用预先设置的处理函数,可安全地执行资源释放、程序退出等逻辑。
- 支持信号的添加、移除和取消,适用于服务端程序的优雅关闭(如接收
SIGTERM 后停止监听新连接、处理完现有请求再退出)。
6. 跨平台兼容性
Asio 的设计目标之一是'一次编写,多平台运行',其底层适配了主流操作系统的 I/O 模型:
- Linux:基于 epoll(边缘触发/水平触发)实现高效事件通知。
- Windows:基于 IOCP(I/O Completion Port)实现异步 I/O,支持重叠 I/O(Overlapped I/O)。
- macOS/iOS:基于 kqueue 实现事件驱动,同时支持 select/poll 作为 fallback。
- 其他系统:支持 FreeBSD、Solaris 等类 Unix 系统,以及嵌入式 Linux(如 ARM 架构)。
开发者无需关注底层操作系统差异,只需使用 Asio 提供的统一接口,即可确保代码在不同平台上的一致性和高效性。
7. 可扩展的 I/O 执行策略
Asio 的核心调度器(io_context)支持自定义 I/O 执行策略,允许开发者根据应用场景优化性能:
- 单线程执行:单个
io_context 在一个线程中运行,适用于 I/O 密集型场景,避免线程同步开销。
- 多线程执行:多个线程同时调用
io_context::run(),实现'线程池'模式,适用于 I/O 操作中包含少量计算的场景,充分利用多核 CPU。
strand 序列化:通过 io_context::strand 确保多个异步操作的处理函数在同一'执行链'中串行执行,避免数据竞争,无需显式使用互斥锁(std::mutex)。
- 自定义执行器:支持 C++20
std::execution 标准,可集成第三方执行器(如线程池库),进一步扩展调度能力。
为什么选择 Asio?
在 C++ 异步编程领域,存在多种解决方案(如 libuv、Poco 库、Qt Network),但 Asio 凭借其独特优势,成为众多开发者的首选:
1. 极致的性能效率
Asio 直接封装操作系统底层的高效 I/O 机制(epoll、IOCP、kqueue),避免了中间层的性能损耗。其核心优势体现在:
- 无线程开销:单线程可处理数千甚至数万并发连接,无需为每个连接创建线程,减少线程栈内存占用(通常每个线程栈大小为 1-8MB)和上下文切换开销(每次切换约消耗 1-10 微秒)。
- 低延迟:基于事件驱动模型,I/O 操作完成后立即触发处理,无需等待线程唤醒,延迟通常可控制在毫秒甚至微秒级。
- 高吞吐量:通过'批量事件处理'优化,减少系统调用次数(如 epoll_wait 一次可获取多个就绪事件),提升单位时间内的 I/O 处理能力。
例如,在 Linux 平台上,一个基于 Asio 的 TCP 服务器(单线程)可轻松处理 10 万级并发连接,且 CPU 利用率保持在较低水平(相比多线程模型,CPU 占用可降低 50% 以上)。
2. 优雅的现代 C++ 接口
Asio 的接口设计严格遵循现代 C++(C++11 及以上)的风格和原则,提供了类型安全、可扩展的编程体验:
- 类型安全:通过强类型枚举(如
ip::tcp、ip::udp)、模板类(如 basic_socket)避免隐式类型转换错误,编译期即可捕获大部分使用错误。
- 泛型编程:支持函数对象、lambda 表达式、函数指针等多种回调形式,兼容
std::bind 和 C++20 协程,代码灵活性高。
- 资源管理:所有 I/O 对象(如
socket、timer)均采用 RAII(资源获取即初始化)模式,自动管理文件描述符、句柄等系统资源,避免内存泄漏和资源泄漏。
- 标准库集成:与 C++ 标准库(如
std::string、std::vector、std::chrono)无缝集成,同时兼容 Boost 库生态(如 Boost.SmartPtr、Boost.Utility),降低学习和迁移成本。
3. 成熟稳定的工业级质量
Asio 自 2003 年发布以来,经过近 20 年的迭代和工业实践检验,其稳定性和可靠性已得到广泛认可:
- 活跃的社区支持:作为 Boost 库的核心组件,Asio 拥有庞大的开发者社区,官方文档(Boost.Asio Documentation)完善,且有大量开源项目(如 WebSocket++、cpp-netlib)基于其构建。
- 严格的测试:Asio 的代码经过严格的单元测试、集成测试和跨平台测试,覆盖了各种异常场景(如网络中断、资源耗尽、信号中断),确保在生产环境中的稳定性。
- 长期维护:Christopher M. Kohlhoff 仍主导 Asio 的开发,且定期发布更新,跟进 C++ 标准的发展(如 C++20 协程、C++23 网络库),保证库的前瞻性。
4. 灵活的使用场景
Asio 的设计不局限于特定领域,可广泛应用于各种 I/O 密集型和并发密集型场景:
- 网络服务端:Web 服务器、API 网关、即时通讯服务器(IM)、游戏服务器、物联网(IoT)网关等。
- 网络客户端:高性能爬虫、分布式系统中的节点通信、实时数据采集工具等。
- 本地 I/O 应用:串口通信工具、定时任务调度器、日志收集系统等。
- 嵌入式开发:嵌入式 Linux 平台上的网络应用(如路由器、智能设备),因资源受限,更需要高效的异步模型。
例如,知名开源项目 NGINX 的 C++ 端口 NGINX++、WebSocket 库 WebSocket++、分布式计算框架 Apache Arrow 等均采用 Asio 作为底层 I/O 引擎。
Asio 的两种版本
Asio 提供两种分发版本,两者在 API 设计和核心功能上完全一致,但依赖关系和集成方式不同,开发者可根据项目需求选择:
| 特性 | Boost.Asio(Boost 集成版) | Standalone Asio(独立版) |
|---|
| 依赖关系 | 依赖 Boost 库的其他组件(如 Boost.System、Boost.Date_Time) | 无外部依赖(仅需 C++11 及以上标准库) |
| 获取方式 | 随 Boost 库一起安装(如 libboost-all-dev) | 单独下载(Asio 官网)或通过包管理器(如 vcpkg) |
| 编译方式 | 需链接 Boost 相关库(如 -lboost_system) | 无需链接额外库(头文件 + 少量源文件) |
| 适用场景 | 项目已依赖 Boost 库,或需要使用 Boost 生态的其他组件 | 项目不希望引入 Boost 依赖,或需要轻量级集成 |
| 版本更新 | 与 Boost 库版本同步(每 3 个月发布一次) | 独立更新,更新频率更高(通常每月有小更新) |
| 许可证 | Boost Software License(开源、商业友好) | Boost Software License(与 Boost 一致) |
版本选择建议
- 选择 Boost.Asio:如果你的项目已经使用 Boost 库(如 Boost.SmartPtr、Boost.Serialization),或需要使用 Boost.Asio 特有的扩展功能(如 Boost.SSL 集成),建议直接使用 Boost.Asio,避免重复依赖。
- 选择 Standalone Asio:如果你的项目追求轻量级,或不希望引入 Boost 的庞大依赖(Boost 库完整安装后约占数百 MB 磁盘空间),建议使用 Standalone Asio。独立版仅需包含头文件和一个源文件(
asio.cpp),即可集成到项目中。
需要注意的是,两种版本的 API 完全兼容,开发者可在项目后期根据需求无缝切换(如从独立版迁移到 Boost 版,只需修改头文件包含路径和链接选项)。
基本编程模型
Asio 的核心设计基于'反应器模式'(Reactor Pattern),这是一种事件驱动的并发编程模式,其核心思想是'将 I/O 操作的触发和处理分离'——由操作系统监听 I/O 事件(如'socket 可读''定时器超时'),当事件发生时,通知应用程序执行对应的处理逻辑。Asio 的基本编程流程可概括为以下 5 个步骤:
步骤 1:创建 I/O 上下文(io_context)
io_context 是 Asio 的核心组件,相当于'事件调度器',负责管理 I/O 事件的注册、监听和分发。所有 Asio 的 I/O 对象(如 socket、timer)都必须与 io_context 关联,才能进行异步操作。
#include <asio.hpp>
int main() {
asio::io_context io;
return 0;
}
io_context 的核心作用是维护一个'事件队列',当异步操作完成时,对应的'完成事件'会被加入队列;io_context::run() 方法则会循环处理队列中的事件,调用对应的处理函数,直到队列为空且没有未完成的异步操作。
步骤 2:创建 I/O 对象并关联 io_context
I/O 对象是 Asio 中与具体 I/O 资源交互的载体,如 steady_timer(定时器)、ip::tcp::socket(TCP 客户端)、ip::tcp::acceptor(TCP 服务器)等。所有 I/O 对象的构造函数都需要传入 io_context 对象,以建立关联。
asio::steady_timer t(io, asio::chrono::seconds(5));
asio::ip::tcp::socket sock(io);
I/O 对象的生命周期与 io_context 绑定——当 io_context 被销毁时,所有关联的 I/O 对象也会自动释放资源(如关闭 Socket、取消定时器)。
步骤 3:启动异步操作并指定完成处理程序
Asio 的所有 I/O 操作都提供'异步版本'(方法名以 async_ 开头),如 async_wait(定时器异步等待)、async_connect(Socket 异步连接)、async_read(异步读取数据)等。启动异步操作时,需要传入一个'完成处理程序'(Completion Handler)——这是一个函数对象(如 lambda、函数指针、std::function),当异步操作完成(成功或失败)时,io_context 会调用该处理程序。
完成处理程序的签名由具体的异步操作定义,通常第一个参数是 asio::error_code 类型,用于表示操作的结果(error_code::value() == 0 表示成功,否则表示失败);后续参数根据操作类型而定(如 async_read 的处理程序会包含'读取的字节数')。
例如,为定时器启动异步等待,并指定 lambda 作为完成处理程序:
t.async_wait([](const asio::error_code& ec) {
if (!ec) {
std::cout << "Timer expired! Hello, Asio!" << std::endl;
} else {
std::cout << "Timer error: " << ec.message() << std::endl;
}
});
步骤 4:运行 io_context 的事件循环
io_context::run() 方法是 Asio 事件循环的入口,它会阻塞当前线程,不断从'事件队列'中取出完成事件,并调用对应的完成处理程序,直到满足以下两个条件之一才会返回:
- 所有异步操作已完成(无未处理的事件,且无正在等待的 I/O 操作);
- 调用
io_context::stop() 或 io_context::restart() 方法主动终止事件循环。
在之前的定时器示例中,启动异步操作后,必须调用 io.run() 才能触发事件循环:
需要注意的是,io_context::run() 是'阻塞式'的——如果没有启动任何异步操作,run() 会立即返回(因为事件队列为空);如果有正在等待的异步操作(如定时器未超时、Socket 未连接),run() 会阻塞线程,直到这些操作完成并处理完所有事件。
此外,io_context 支持多线程并发调用 run()——当多个线程同时调用 run() 时,io_context 会将事件分发到不同线程中执行,实现'线程池'模式。但需注意,默认情况下,同一个异步操作的完成处理程序可能在不同线程中执行,若处理程序操作共享数据,需通过 strand(执行链)确保串行执行,避免数据竞争。
步骤 5:处理异步操作结果
当异步操作完成后,io_context 会调用对应的完成处理程序,并通过 asio::error_code 参数传递操作结果。开发者需要在处理程序中检查错误状态,并执行相应的逻辑(如重试操作、释放资源、终止程序等)。
- 定时器被取消(
ec == asio::error::operation_aborted);
- Socket 连接失败(
ec == asio::error::connection_refused);
- 读取数据时连接被关闭(
ec == asio::error::eof);
- 系统资源不足(
ec == asio::error::resource_unavailable_try_again)。
例如,在 TCP 客户端连接的处理程序中处理错误:
sock.async_connect(endpoint, [&sock](const asio::error_code& ec) {
if (!ec) {
std::cout << "Connected to server successfully!" << std::endl;
char buf[1024];
sock.async_read_some(asio::buffer(buf), [&sock, buf](const asio::error_code& read_ec, std::size_t bytes_read) {
if (!read_ec) {
std::cout << "Received data: " << std::string(buf, bytes_read) << std::endl;
} else if (read_ec == asio::error::eof) {
std::cout << "Connection closed by server." << std::endl;
} else {
std::cout << "Read error: " << read_ec.message() << std::endl;
}
});
} else {
std::cout << "Connect failed: " << ec.message() << std::endl;
}
});
进阶示例:TCP 回声服务器
为了更直观地理解 Asio 的编程模型,下面实现一个简单的 TCP 回声服务器——服务器监听指定端口,接收客户端连接后,将客户端发送的数据原封不动地回传(即'回声'功能)。该示例将展示 io_context、ip::tcp::acceptor(服务器监听)、ip::tcp::socket(客户端连接)的协同工作,以及异步操作的链式调用。
完整代码
#include <iostream>
#include <memory>
#include <asio.hpp>
using asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
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(asio::buffer(data_, max_length), [this, self](const asio::error_code& ec, std::size_t bytes_read) {
if (!ec) {
do_write(bytes_read);
} else if (ec == asio::error::eof) {
std::cout << "Client disconnected: " << socket_.remote_endpoint().address() << std::endl;
} else {
std::cerr << "Read error: " << ec.message() << std::endl;
}
});
}
void do_write(std::size_t length) {
auto self(shared_from_this());
asio::async_write(socket_, asio::buffer(data_, length), [this, self](const asio::error_code& ec, std::size_t ) {
if (!ec) {
do_read();
} else {
std::cerr << "Write error: " << ec.message() << std::endl;
}
});
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class Server {
public:
Server(asio::io_context& io_context, short port) : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
do_accept();
}
private:
void do_accept() {
acceptor_.async_accept([this](const asio::error_code& ec, tcp::socket socket) {
if (!ec) {
std::cout << "New client connected: " << socket.remote_endpoint().address() << std::endl;
std::make_shared<Session>(std::move(socket))->start();
} else {
std::cerr << "Accept error: " << ec.message() << std::endl;
}
do_accept();
});
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: tcp_echo_server <port>\n";
return 1;
}
asio::io_context io_context;
Server server(io_context, std::atoi(argv[1]));
std::cout << "Echo server started on port " << argv[1] << ", waiting for clients..." << std::endl;
io_context.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
代码解析
- Session 类:
- 负责处理单个客户端的生命周期,使用
std::enable_shared_from_this 确保在异步处理程序执行期间,对象不会被提前销毁(避免悬空指针)。
do_read():异步读取客户端发送的数据,读取成功后调用 do_write() 回传数据;若发生错误(如客户端断开连接),则输出错误信息。
do_write():异步将读取到的数据回传给客户端,写入成功后再次调用 do_read(),形成'读取 - 写入 - 读取'的循环,持续处理客户端数据。
- Server 类:
tcp::acceptor:用于监听指定端口的 TCP 连接请求,构造时绑定到 IPv4 地址和指定端口(如 8080)。
do_accept():异步接受客户端连接,接受成功后创建 Session 对象并调用 start() 启动会话;无论是否成功,都会再次调用 do_accept(),确保服务器持续接受新连接。
- main 函数:
- 解析命令行参数(端口号),创建
io_context 和 Server 对象。
- 调用
io_context.run() 启动事件循环,服务器开始监听并处理客户端连接。
运行方式
测试客户端:使用 telnet 或 nc(netcat)工具连接服务器,发送数据后会收到回声:
telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Hello Asio!
nc localhost 8080
Test Echo Server
Test Echo Server
服务器会输出:Echo server started on port 8080, waiting for clients...
编译:需链接 Asio 相关库(以 Standalone Asio 为例,编译命令如下):
g++ -std=c++11 tcp_echo_server.cpp -o tcp_echo_server -lasio
若使用 Boost.Asio,需链接 Boost.System 库:
g++ -std=c++11 tcp_echo_server.cpp -o tcp_echo_server -lboost_system -pthread
New client connected: 127.0.0.1
New client connected: 127.0.0.1
Client disconnected: 127.0.0.1
安装和配置(补充细节)
使用 Boost.Asio
1. 源码安装(适用于需要自定义编译选项的场景)
- 下载 Boost 源码:从 Boost 官网 下载最新版本(如 Boost 1.85.0),解压到本地目录(如
/usr/local/src/boost_1_85_0)。
export LD_LIBRARY_PATH=/usr/local/boost/lib:$LD_LIBRARY_PATH
echo 'export LD_LIBRARY_PATH=/usr/local/boost/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
cd /usr/local/src/boost_1_85_0
./bootstrap.sh --prefix=/usr/local/boost
./b2 --with-system -j4 install
2. 在 CMake 项目中精细配置
若项目仅需 Boost.Asio,无需链接整个 Boost 库,可在 CMakeLists.txt 中指定具体依赖:
cmake_minimum_required(VERSION 3.10)
project(tcp_echo_server)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找 Boost 库,仅需 system 组件(Asio 依赖)
find_package(Boost 1.70 REQUIRED COMPONENTS system)
# 添加可执行文件
add_executable(tcp_echo_server tcp_echo_server.cpp)
# 链接 Boost.System 库
target_link_libraries(tcp_echo_server Boost::system pthread # Linux 下需链接 pthread 库(Boost.Asio 依赖线程支持))
# 指定 Boost 头文件路径(若 Boost 安装在非标准路径)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
endif()
使用独立 Asio
1. 源码集成(适用于轻量级项目)
- 下载独立 Asio:从 Asio 官网 下载最新版本(如 asio-1.28.1),解压后得到
asio-1.28.1 目录,其中 include/asio 为头文件目录,src/asio.cpp 为唯一需要编译的源文件。
- 项目集成:
- 将
include/asio 目录复制到项目的 include 目录下。
- 将
src/asio.cpp 复制到项目的 src 目录下。
编译时包含头文件路径,并将 asio.cpp 一起编译:
g++ -std=c++11 src/main.cpp src/asio.cpp -o my_app -Iinclude -pthread
2. 在 CMake 项目中配置
独立 Asio 可通过 find_package 或直接集成源码,以下是两种常见配置方式:
方式 1:通过 Vcpkg 安装后配置
cmake_minimum_required(VERSION 3.10)
project(my_asio_project)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找 Vcpkg 安装的 Asio
find_package(asio REQUIRED)
# 添加可执行文件
add_executable(my_app main.cpp)
# 链接 Asio 库(独立版 Asio 通常为头文件库,仅需链接依赖的系统库)
target_link_libraries(my_app asio::asio pthread # Linux 下需链接 pthread)
方式 2:直接集成源码(无需安装)
cmake_minimum_required(VERSION 3.10)
project(my_asio_project)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加 Asio 头文件路径(假设 asio 目录在项目根目录下)
include_directories(${PROJECT_SOURCE_DIR}/asio/include)
# 添加 Asio 源文件(仅需编译 asio.cpp)
add_library(asio STATIC ${PROJECT_SOURCE_DIR}/asio/src/asio.cpp)
# 添加可执行文件
add_executable(my_app main.cpp)
# 链接 Asio 静态库和系统库
target_link_libraries(my_app asio pthread)
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online