boost创建一个服务端
1. Reactor 模式
Boost.Asio 基于 Reactor 模式(也称为事件驱动模式):
- 一个中心 事件循环(io_context)不断检查事件
- 当事件就绪时(如数据到达、连接请求),调用相应的回调函数
- 避免为每个连接创建线程,资源利用率高
2. Proactor 模式扩展
Asio 实际上是 Proactor 模式的实现:
- 应用程序发起异步操作
- 操作系统执行实际 I/O
- 操作完成后,Asio 在事件循环中调用完成处理程序
组件工作原理
1. io_context - 事件调度中心
boost::asio::io_context io_context_;
作用:Asio 的核心,负责:
- 管理所有异步操作
- 分发 I/O 事件到相应的完成处理程序
- 提供事件循环机制
工作流程:
启动 → 检查就绪事件 → 调用回调 → 再检查 → ...
2. acceptor - 连接接收器
tcp::acceptor acceptor_(io_context, tcp::endpoint(tcp::v4(), port));
工作原理:
客户端连接请求 → 操作系统TCP栈 → acceptor检测到 → 调用async_accept回调
3. 异步操作链
连接接受流程:
void do_accept() {
acceptor_.async_accept([this](error_code ec, tcp::socket socket) {
if (!ec) {
std::make_shared<Session>(std::move(socket))->start();
}
do_accept(); // ⬅️ 关键:递归调用,持续监听新连接
});
}
数据读取流程:
void do_read() {
socket_.async_read_some(
boost::asio::buffer(data_),
[this, self](error_code ec, std::size_t length) {
if (!ec) {
do_write(length); // ⬅️ 读取成功后写入
}
});
}
数据写入流程:
void do_write(std::size_t length) {
boost::asio::async_write(
socket_,
boost::asio::buffer(data_, length),
[this, self](error_code ec, std::size_t /*length*/) {
if (!ec) {
do_read(); // ⬅️ 写入成功后继续读取
}
});
}
关键机制详解
1. 异步操作链
accept → read → write → read → write → ...
- 每个异步操作完成时,启动下一个操作
- 形成永不停歇的处理链条
- 自动维持连接的生命周期
2. 共享所有权与生命周期管理
class Session : public std::enable_shared_from_this<Session> {
// 使用 shared_ptr 确保 Session 在异步操作期间保持存活
};
原理:
- 异步操作可能在任何时间完成
- 使用
shared_ptr确保回调执行时对象仍然存在 enable_shared_from_this允许在成员函数中获取自身的shared_ptr
3. 多线程处理模型
// 主线程创建工作者线程
std::vector<std::thread> threads;
for (std::size_t i = 0; i < thread_pool_size_; ++i) {
threads.emplace_back([this]() {
io_context_.run(); // ⬅️ 每个线程运行独立的事件循环
});
}
线程模型:
主线程
│
├── 工作者线程1 → io_context.run()
├── 工作者线程2 → io_context.run()
├── 工作者线程3 → io_context.run()
└── 工作者线程4 → io_context.run()
关键点:
- 所有线程共享同一个
io_context - 操作系统负责将就绪事件分配到空闲线程
- 内置同步机制,线程安全
4. 信号处理与优雅关闭
boost::asio::signal_set signals_(io_context_);
signals_.add(SIGINT);
signals_.add(SIGTERM);
signals_.async_wait([this](error_code /*ec*/, int /*signo*/) {
io_context_.stop(); // ⬅️ 停止事件循环
});
关闭流程:
- 用户按下 Ctrl+C 产生 SIGINT 信号
- Asio 捕获信号,调用注册的回调
- 回调中调用
io_context.stop() - 所有线程的
run()方法返回 - 程序正常退出
性能优势原理
1. 避免线程爆炸
- 传统方案:一个连接一个线程
- Asio 方案:固定线程池 + 异步 I/O
- 可处理数千个并发连接而不会创建数千个线程
2. 零拷贝优化
socket_.async_read_some(boost::asio::buffer(data_));
- 数据直接从网卡缓冲区读到应用缓冲区
- 减少内存拷贝次数
3. 系统调用批处理
- 多个异步操作在一次系统调用中处理
- 减少用户态-内核态切换开销
事件循环内部机制
io_context.run() 的工作流程:
while (有未完成的操作 || 有就绪的事件) {
1. 检查是否有完成的异步操作
2. 如果有,调用对应的完成处理程序
3. 如果没有,阻塞等待新事件
4. 处理新到达的事件
}
这种设计使得 Boost.Asio 服务端能够以极高的效率处理大量并发连接,是现代高性能网络编程的范实现。
std::make_shared(std::move(socket))->start() 这种模式提供了:
安全的所有权转移 - 使用 std::move
自动生命周期管理 - 使用 shared_ptr + enable_shared_from_this
异常安全 - 资源自动释放
高性能 - make_shared 优化内存分配
自然的异步编程模型 - 对象生命周期与异步操作匹配
这是现代 C++ 异步服务器编程中的最佳实践,结合了 RAII、智能指针和移动语义等核心特性。
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
#include <string>
using boost::asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
public:
Session(tcp::socket socket) : socket_(std::move(socket)) {
std::cout << "Session 构造函数" << std::endl;
}
void start() {
std::cout << "Session::start() 调用" << std::endl;
try {
auto endpoint = socket_.remote_endpoint();
std::cout << "客户端连接: " << endpoint << std::endl;
// 设置socket选项
boost::system::error_code opt_ec;
socket_.set_option(tcp::no_delay(true), opt_ec);
if (opt_ec) {
std::cerr << "设置no_delay错误: " << opt_ec.message() << std::endl;
}
send_welcome();
}
catch (const std::exception& e) {
std::cerr << "获取客户端端点异常: " << e.what() << std::endl;
// 即使有异常也尝试发送欢迎消息
send_welcome();
}
}
private:
void send_welcome() {
std::cout << "Session::send_welcome() 调用" << std::endl;
auto self(shared_from_this());
// 检查socket状态
boost::system::error_code ec;
auto endpoint = socket_.remote_endpoint(ec);
if (ec) {
std::cerr << "检查socket状态错误: " << ec.message() << std::endl;
return;
}
std::string welcome_msg = "欢迎连接到服务器! 发送任何消息将会回显.\r\n";
std::cout << "准备发送欢迎消息: " << welcome_msg.length() << " 字节" << std::endl;
// 使用async_write确保全部数据发送
boost::asio::async_write(
socket_,
boost::asio::buffer(welcome_msg),
[this, self, welcome_msg](boost::system::error_code ec, std::size_t length) {
std::cout << "欢迎消息回调执行, ec: " << ec.message()
<< ", 长度: " << length << std::endl;
if (!ec) {
if (length == welcome_msg.length()) {
std::cout << "欢迎消息完整发送" << std::endl;
}
else {
std::cout << "欢迎消息部分发送: " << length << "/" << welcome_msg.length() << std::endl;
}
do_read();
}
else {
std::cerr << "发送欢迎消息错误: " << ec.message() << std::endl;
// 即使发送失败也继续读取
do_read();
}
});
}
void do_read() {
std::cout << "Session::do_read() 调用" << std::endl;
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) {
std::cout << "读取回调执行, ec: " << ec.message()
<< ", 长度: " << length << std::endl;
if (!ec && length > 0) {
// 确保字符串正确终止
if (length < max_length) {
data_[length] = '\0';
}
else {
data_[max_length - 1] = '\0';
length = max_length - 1;
}
std::string received_data(data_, length);
std::cout << "收到数据: \"" << received_data << "\"" << std::endl;
do_write(length);
}
else if (ec) {
handle_error(ec, "读取");
}
else {
std::cout << "读取到0字节数据" << std::endl;
do_read(); // 继续读取
}
});
}
void do_write(std::size_t length) {
auto self(shared_from_this());
std::string echo_msg = "服务器回显: " + std::string(data_, length) + "\r\n";
boost::asio::async_write(
socket_,
boost::asio::buffer(echo_msg),
[this, self, echo_msg](boost::system::error_code ec, std::size_t written) {
std::cout << "回显回调执行, ec: " << ec.message()
<< ", 写入: " << written << " 字节" << std::endl;
if (!ec) {
std::cout << "回显消息发送成功: \"" << echo_msg << "\"" << std::endl;
do_read();
}
else {
std::cerr << "回显写入错误: " << ec.message() << std::endl;
}
});
}
void handle_error(boost::system::error_code ec, const std::string& operation) {
if (ec == boost::asio::error::eof) {
std::cout << "客户端正常断开连接" << std::endl;
}
else if (ec == boost::asio::error::operation_aborted) {
std::cout << "操作被取消" << std::endl;
}
else {
std::cerr << operation << "错误: " << ec.message() << std::endl;
}
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
// 服务器类
class Server {
public:
Server(boost::asio::io_context& io_context, short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
std::cout << "服务器启动,监听端口: " << port << std::endl;
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();
}
else {
std::cerr << "接受连接错误: " << ec.message() << std::endl;
}
// 继续接受下一个连接
do_accept();
});
}
tcp::acceptor acceptor_;
};
// 带线程池的服务器
class ThreadPoolServer {
public:
ThreadPoolServer(short port, std::size_t thread_pool_size = 4)
: io_context_(),
signals_(io_context_),
server_(io_context_, port),
thread_pool_size_(thread_pool_size) {
// 注册信号处理,用于优雅关闭
signals_.add(SIGINT);
signals_.add(SIGTERM);
do_await_stop();
}
void run() {
// 创建线程池
std::vector<std::thread> threads;
for (std::size_t i = 0; i < thread_pool_size_; ++i) {
threads.emplace_back([this]() {
try {
std::cout << "线程 " << std::this_thread::get_id() << " 开始运行" << std::endl;
io_context_.run();
std::cout << "线程 " << std::this_thread::get_id() << " 结束运行" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "IO上下文运行异常: " << e.what() << std::endl;
}
});
}
std::cout << "服务器运行中,使用 " << thread_pool_size_ << " 个工作线程" << std::endl;
std::cout << "按 Ctrl+C 停止服务器" << std::endl;
// 等待所有线程完成
for (auto& thread : threads) {
thread.join();
}
}
private:
void do_await_stop() {
signals_.async_wait([this](boost::system::error_code /*ec*/, int /*signo*/) {
std::cout << "\n正在停止服务器..." << std::endl;
io_context_.stop();
});
}
boost::asio::io_context io_context_;
boost::asio::signal_set signals_;
Server server_;
std::size_t thread_pool_size_;
};
int main(int argc, char* argv[]) {
try {
short port = 8080;
if (argc == 2) {
port = std::atoi(argv[1]);
}
std::cout << "启动 Boost.Asio 服务器..." << std::endl;
ThreadPoolServer server(port);
server.run();
std::cout << "服务器已停止" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "异常: " << e.what() << std::endl;
return 1;
}
return 0;
}
719

被折叠的 条评论
为什么被折叠?



