一、什么是boost.asio
Boost.Asio是Boost C++库中的一个组件主要用于:
网络编程(TCP/UDP)
异步 I/O 操作
定时器
串口通信(通过 boost::asio::serial_port)
文件 I/O(有限支持)
它基于 Proactor 模式,使用回调函数或协程来处理异步操作。
Proactor 模式是 异步 I/O 编程 中的一种设计模式,广泛应用于高性能网络服务器和系统编程中,特别是在使用像 Boost.Asio、libevent、Windows I/O Completion Ports (IOCP) 等异步 I/O 框架时。
io_context :核心调度器,管理所有异步操作
socket :表示 TCP 或 UDP 套接字
async_read, async_write: 异步读写操作
async_wait :定时器等待
resolver: DNS 解析器
strand :保证线程安全的顺序执行
deadline_timer, steady_timer :定时器
以下是TCP客户端示例(同步)
#include <boost/asio.hpp> // Boost.Asio 主要头文件,包含网络、I/O 等功能
#include <iostream> // 标准输入输出流,用于打印响应内容
int main() {
// 创建 io_context 对象
// 这是 Boost.Asio 的核心类,负责管理 I/O 操作的调度(事件循环)
boost::asio::io_context io;
// 创建一个 TCP 套接字对象
// 所有数据的发送和接收都通过这个 socket 对象完成
boost::asio::ip::tcp::socket socket(io);
// 创建一个解析器 resolver
// 用于将主机名(域名)和端口号转换成具体的 IP 地址和端口
boost::asio::ip::tcp::resolver resolver(io);
// 使用 resolver 解析 "example.com" 和服务 "http"(即端口 80)
// 返回一个 endpoint 迭代器列表,然后使用 connect 函数连接到第一个有效的地址
boost::asio::connect(socket, resolver.resolve("example.com", "http"));
// 构造 HTTP 请求报文
std::string request =
"GET / HTTP/1.1\r\n"
"Host: example.com\r\n"
"Connection: close\r\n"
"\r\n";
// 将请求发送到服务器
// boost::asio::buffer() 将字符串包装成缓冲区格式
// write() 函数会阻塞直到所有数据被写入 socket
boost::asio::write(socket, boost::asio::buffer(request));
// 创建一个字符数组作为接收缓冲区,大小为 4096 字节
char response[4096];
// 从 socket 中读取响应数据
// read_some() 是同步函数,会阻塞直到收到一些数据
// 返回值 len 表示实际读取的字节数
size_t len = socket.read_some(boost::asio::buffer(response));
// 将收到的数据写入标准输出(控制台),显示服务器返回的内容
std::cout.write(response, len);
return 0;
}
CP客户端示例(异步)
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
using boost::asio::ip::tcp;
int main()
{
try {
// 创建 io_context 对象,它是所有异步操作的核心调度器
boost::asio::io_context io;
// 使用智能指针管理 socket 生命周期,防止异步回调中访问已销毁对象
auto socket = std::make_shared<tcp::socket>(io);
// 创建解析器 resolver,用于将域名和端口解析为 IP 地址
tcp::resolver resolver(io);
// 解析目标地址:example.com:80 (HTTP)
// 注意:resolve 是同步的,实际项目中也可以改为异步 resolve
auto endpoints = resolver.resolve("example.com", "http");
// 异步连接到服务器
boost::asio::async_connect(*socket, endpoints,
[socket](const boost::system::error_code& ec, const tcp::endpoint&) {
if (ec)
{
std::cerr << "连接失败: " << ec.message() << std::endl;
return;
}
std::cout << "连接成功,正在发送 HTTP 请求..." << std::endl;
// 构造 HTTP 请求报文
std::string request =
"GET / HTTP/1.1\r\n"
"Host: example.com\r\n"
"Connection: close\r\n"
"\r\n";
// 异步发送请求数据
boost::asio::async_write(*socket, boost::asio::buffer(*request.c_str(), request.size()),
[socket](const boost::system::error_code& ec, std::size_t /*bytes_transferred*/)
{
if (ec)
{
std::cerr << "发送请求失败: " << ec.message() << std::endl;
return;
}
std::cout << "请求已发送,等待响应..." << std::endl;
// 准备接收缓冲区
auto response = std::make_shared<std::vector<char>>(4096);
// 异步读取响应数据
socket->async_read_some(boost::asio::buffer(*response),
[socket, response](const boost::system::error_code& ec, std::size_t len)
{
if (ec)
{
std::cerr << "接收响应失败: " << ec.message() << std::endl;
return;
}
std::cout << "收到响应数据:" << std::endl;
std::cout.write(response->data(), static_cast<std::streamsize>(len));
std::cout << std::endl;
});
});
});
// 启动异步事件循环,开始处理异步操作
io.run();
}
catch (std::exception& e) {
std::cerr << "异常: " << e.what() << std::endl;
}
return 0;
}
boost::asio::io_context: 所有异步操作的调度核心
async_connect() :异步连接服务器,完成后调用回调函数
async_write() :异步发送 HTTP 请求
async_read_some() :异步读取服务器返回的数据
shared_ptr<socket>: 防止在异步回调执行前 socket 被销毁
main()
↓
创建 io_context + socket + resolver
↓
resolver.resolve("example.com", "http")
↓
async_connect(socket, endpoint)
↓
[连接成功] → async_write(request)
↓
[发送完成] → async_read_some(response)
↓
[接收完成] → 输出响应内容
C++ 11中可以使用std::bind 来简化参数绑定、避免手动捕获上下文或重复传参
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <functional> // std::bind, std::placeholders
// 使用 boost.asio 的 tcp 命名空间
using boost::asio::ip::tcp;
// 使用占位符 _1, _2 等,用于回调参数绑定
namespace placeholders = std::placeholders;
/**
* 连接完成后的回调函数
*/
void handle_connect(const boost::system::error_code& ec,
tcp::socket* socket, // 套接字指针
const std::string& request, // HTTP 请求内容
std::shared_ptr<std::vector<char>> buffer)
{ // 接收缓冲区
if (ec)
{
std::cerr << "连接失败: " << ec.message() << std::endl;
return;
}
std::cout << "连接成功,正在发送 HTTP 请求..." << std::endl;
// 异步写入 HTTP 请求数据
boost::asio::async_write(*socket, boost::asio::buffer(request),
std::bind(&handle_write, placeholders::_1, placeholders::_2, socket, buffer));
}
/**
* 发送请求完成后的回调函数
*/
void handle_write(const boost::system::error_code& ec,
std::size_t /*bytes_transferred*/, // 已发送字节数(未使用)
tcp::socket* socket, // 套接字指针
std::shared_ptr<std::vector<char>> buffer) // 接收缓冲区
{
if (ec)
{
std::cerr << "发送请求失败: " << ec.message() << std::endl;
return;
}
std::cout << "请求已发送,等待响应..." << std::endl;
// 异步读取服务器返回的数据
socket->async_read_some(boost::asio::buffer(*buffer),
std::bind(&handle_read, placeholders::_1, placeholders::_2, buffer));
}
/**
* 接收响应数据后的回调函数
*/
void handle_read(const boost::system::error_code& ec,
std::size_t len, // 实际读取到的字节数
std::shared_ptr<std::vector<char>> buffer)
{ // 接收缓冲区
if (ec)
{
std::cerr << "接收响应失败: " << ec.message() << std::endl;
return;
}
std::cout << "收到响应数据:" << std::endl;
// 打印接收到的数据
std::cout.write(buffer->data(), static_cast<std::streamsize>(len));
std::cout << std::endl;
}
int main()
{
try {
// 创建 io_context 对象,是所有异步操作的核心调度器
boost::asio::io_context io;
// 使用智能指针管理 socket 生命周期,防止异步回调中访问已销毁对象
auto socket = std::make_shared<tcp::socket>(io);
// 分配一个大小为 4096 的缓冲区用于接收响应数据
auto buffer = std::make_shared<std::vector<char>>(4096);
// 构造 HTTP GET 请求报文
std::string request =
"GET / HTTP/1.1\r\n"
"Host: example.com\r\n"
"Connection: close\r\n" // 表示请求完成后关闭连接
"\r\n"; // 请求头结束标志
// 创建解析器 resolver,用于将域名和端口解析为 IP 地址
tcp::resolver resolver(io);
// 解析目标地址:example.com:80 (HTTP)
auto endpoints = resolver.resolve("example.com", "http");
// 异步连接到服务器
boost::asio::async_connect(*socket, endpoints,
std::bind(handle_connect, placeholders::_1, socket.get(), request, buffer));
std::cout << "启动事件循环..." << std::endl;
// 启动异步事件循环,开始处理异步操作
io.run();
}
catch (std::exception& e)
{
// 捕获并打印异常信息
std::cerr << "异常: " << e.what() << std::endl;
}
return 0;
}
main()
↓
创建 io_context + socket + buffer + resolver
↓
resolver.resolve("example.com", "http")
↓
async_connect(...) → 触发 handle_connect
↓
handle_connect()
↓
async_write(...) → 触发 handle_write
↓
handle_write()
↓
async_read_some(...) → 触发 handle_read
↓
handle_read() → 输出响应内容
二、std::bind 与boost::asio::connect /boost:;asio::async_connect的区别
类别 std::bind connect async_connect
类型 标准库函数模板 Boost.Asio 同步函数 Boost.Asio 异步函数
作用 绑定函数和参数,生成可调用对象 同步连接服务器 异步连接服务器
是否阻塞主线程 ❌ 不涉及线程,只是绑定参数 ✅ 是(同步) ❌ 否(异步)
何时使用 配合异步回调使用 快速建立同步连接 建立非阻塞连接,配合回调
底层机制 C++11 特性,用于函数封装 直接调用系统 connect 使用 io_context 异步调度
示例代码片段 std::bind(func, _1, obj) connect(socket, endpoints) async_connect(socket, endpoints, handler)