目录
[2.安装方式(适配 CMake/VCPKG)](#2.安装方式(适配 CMake/VCPKG))
[3.核心 API 与使用示例](#3.核心 API 与使用示例)
[4.HTTP 服务器超详细示例](#4.HTTP 服务器超详细示例)
[4.6.启用 HTTPS 服务](#4.6.启用 HTTPS 服务)
[6.与原生 Boost.Asio 的核心差异](#6.与原生 Boost.Asio 的核心差异)
1.简介
Asio2 并非 Boost 官方提供的库,而是一个基于 Boost.Asio 封装的第三方高性能网络编程库,主打简化接口、增强功能、提升开发效率,同时保持跨平台(Windows/Linux/macOS)特性,适配 C++11 及以上标准,非常适合快速开发 TCP/UDP/HTTP/SSL 等网络应用。
- 基于原生 Boost.Asio,兼容 Boost 1.66+ 版本,同时支持 standalone Asio(不依赖完整 Boost 库)。
- 封装了原生 Asio 繁琐的异步回调、缓冲区管理、连接管理等逻辑,提供更简洁的 API。
- 内置断线重连、超时机制、心跳检测、SSL/TLS 加密、HTTP 协议支持,还支持 UDP 组播 / 广播、串口通信等。
- 支持TCP,UDP,HTTP,WEBSOCKET,RPC,ICMP,SERIAL_PORT等。
- 支持可靠UDP(基于KCP),支持SSL,支持从内存字符串加载SSL证书。
- TCP支持数据拆包功能(按指定的分隔符对数据自动进行拆包,保证用户收到的数据是一个完整的数据包);实现了TCP的数据报模式(类似WEBSOCKET)。
- 支持windows,linux,32位,64位。
- 依赖asio(boost::asio或独立asio均可,若需要HTTP功能必须使用boost::asio),依赖C++17。
- 代码采用hpp头文件方式,以源码级链入,无需编译,只需在工程的Include包含目录中添加asio2路径,然后在源码中#include <asio2/asio2.hpp>包含头文件即可。
2.安装方式(适配 CMake/VCPKG)
1.下载地址
https://github.com/zhllxt/asio2.git
https://gitee.com/zhllxt/asio2
2.VCPKG 安装(推荐,符合你的项目构建习惯)
根据平台执行对应命令,自动下载编译并安装:
cpp
# Windows 安装 x64 版本
.\vcpkg install asio2:x64-windows
# Linux 安装 x64 版本
./vcpkg install asio2:x64-linux
# 如需支持 SSL(如 HTTPS/SSL-TCP),安装带 SSL 的版本
.\vcpkg install asio2[ssl]:x64-windows # Windows
./vcpkg install asio2[ssl]:x64-linux # Linux
3.CMake 配置与编译
安装后,在你的 CMakeLists.txt 中直接引用即可,VCPKG 会自动处理依赖路径:
cpp
cmake_minimum_required(VERSION 3.15)
project(asio2_demo)
# 找到 asio2 库
find_package(asio2 REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
# 链接 asio2 及依赖库
target_link_libraries(${PROJECT_NAME} PRIVATE asio2::asio2)
# 指定 C++ 标准
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11)
3.核心 API 与使用示例
Asio2 的接口设计简洁,以 TCP 通信为例,核心场景的示例代码如下:
1.TCP 服务器
cpp
#include <asio2/asio2.hpp>
int main() {
asio2::tcp_server server;
// 连接建立回调
server.bind_connect([](auto &session) {
std::cout << "client connected: " << session.remote_address() << std::endl;
});
// 接收数据回调
server.bind_recv([](auto &session, std::string_view data) {
std::cout << "recv: " << data << std::endl;
session.send(data); // 回声
});
// 启动服务器,监听 8080 端口
server.start("0.0.0.0", 8080);
asio2::executor::run(); // 运行事件循环
return 0;
}
2.TCP 客户端(带断线重连)
cpp
#include <asio2/asio2.hpp>
int main() {
asio2::tcp_client client;
// 启用断线重连
client.enable_reconnect(true, 3000); // 每 3 秒重连一次
// 连接成功后发送数据
client.bind_connect([&](auto &session) {
session.send("hello server");
});
// 启动客户端,连接服务器
client.start("127.0.0.1", 8080);
asio2::executor::run();
return 0;
}
4.HTTP 服务器超详细示例
4.1.服务器架构设计
采用模块化拆分,避免回调地狱,核心模块如下:
- 路由管理器:统一管理 GET/POST 路由,支持路径匹配
- 请求处理器:解析 GET 参数、POST 表单 / JSON 数据
- 静态文件管理器:处理静态资源请求,支持文件类型映射
- 响应构造器:统一封装 HTTP 响应(状态码、响应头、响应体)
- 错误处理器:捕获并返回 400/403/404/500 等标准错误
4.2.完整源代码(分文件组织)
头文件 http_server.h(模块声明)
cpp
#pragma once
#include <asio2/asio2.hpp>
#include <nlohmann/json.hpp>
#include <unordered_map>
#include <string>
#include <functional>
#include <fstream>
// 命名空间别名,简化代码
using json = nlohmann::json;
using TcpSession = asio2::tcp_session;
using HttpRequest = asio2::http_request;
using HttpResponse = asio2::http_response;
using RouteHandler = std::function<void(const HttpRequest&, HttpResponse&)>;
// 1. 路由管理器类:管理 GET/POST 路由映射
class RouteManager {
public:
// 注册 GET 路由
void get(const std::string& path, RouteHandler handler);
// 注册 POST 路由
void post(const std::string& path, RouteHandler handler);
// 匹配路由并执行处理函数
bool match(const std::string& method, const std::string& path, const HttpRequest& req, HttpResponse& resp);
private:
std::unordered_map<std::string, RouteHandler> get_routes_; // GET 路由表
std::unordered_map<std::string, RouteHandler> post_routes_; // POST 路由表
};
// 2. 静态文件管理器类:处理静态资源请求
class StaticFileManager {
public:
// 设置静态文件根目录
void set_root(const std::string& root);
// 处理静态文件请求
bool handle(const std::string& path, HttpResponse& resp);
private:
// 根据文件后缀获取 Content-Type
std::string get_content_type(const std::string& filename);
std::string root_dir_ = "./static/"; // 默认静态文件目录
};
// 3. HTTP 服务器核心类
class HttpServer {
public:
HttpServer();
// 启动服务器
bool start(const std::string& ip, uint16_t port);
// 获取路由管理器(用于注册路由)
RouteManager& router();
private:
// 核心请求处理回调
void on_recv(TcpSession& session, std::string_view data);
// 错误处理
void on_error(TcpSession& session, const boost::system::error_code& ec);
// 404 处理
void handle_404(HttpResponse& resp);
// 500 处理
void handle_500(HttpResponse& resp);
private:
asio2::tcp_server server_;
RouteManager router_;
StaticFileManager static_manager_;
};
源文件 http_server.cpp(模块实现)
cpp
#include "http_server.h"
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
// -------------------------- RouteManager 实现 --------------------------
void RouteManager::get(const std::string& path, RouteHandler handler) {
get_routes_[path] = std::move(handler);
}
void RouteManager::post(const std::string& path, RouteHandler handler) {
post_routes_[path] = std::move(handler);
}
bool RouteManager::match(const std::string& method, const std::string& path, const HttpRequest& req, HttpResponse& resp) {
if (method == "GET" && get_routes_.count(path)) {
get_routes_[path](req, resp);
return true;
}
if (method == "POST" && post_routes_.count(path)) {
post_routes_[path](req, resp);
return true;
}
return false;
}
// -------------------------- StaticFileManager 实现 --------------------------
void StaticFileManager::set_root(const std::string& root) {
root_dir_ = root;
// 确保目录以路径分隔符结尾
if (!root_dir_.empty() && root_dir_.back() != fs::path::preferred_separator) {
root_dir_ += fs::path::preferred_separator;
}
}
std::string StaticFileManager::get_content_type(const std::string& filename) {
std::unordered_map<std::string, std::string> mime_map = {
{".html", "text/html; charset=utf-8"},
{".css", "text/css; charset=utf-8"},
{".js", "application/javascript; charset=utf-8"},
{".txt", "text/plain; charset=utf-8"},
{".jpg", "image/jpeg"},
{".png", "image/png"},
{".json", "application/json; charset=utf-8"}
};
std::string ext = fs::path(filename).extension().string();
return mime_map.count(ext) ? mime_map[ext] : "application/octet-stream";
}
bool StaticFileManager::handle(const std::string& path, HttpResponse& resp) {
// 拼接真实文件路径,防止路径穿越攻击
fs::path real_path = fs::canonical(root_dir_ + path.substr(8)); // 截取 /static/ 后的路径
// 路径校验:必须在静态目录内
if (!fs::exists(real_path) || !fs::is_regular_file(real_path)) {
return false;
}
// 设置响应头和文件内容
resp.status(200, "OK");
resp.set_header("Content-Type", get_content_type(real_path.filename().string()));
// asio2 的 send_file 支持大文件断点续传
resp.body(asio2::send_file(real_path.string()));
return true;
}
// -------------------------- HttpServer 实现 --------------------------
HttpServer::HttpServer() {
// 绑定数据接收回调和错误回调
server_.bind_recv(std::bind(&HttpServer::on_recv, this, std::placeholders::_1, std::placeholders::_2));
server_.bind_error(std::bind(&HttpServer::on_error, this, std::placeholders::_1, std::placeholders::_2));
}
bool HttpServer::start(const std::string& ip, uint16_t port) {
try {
server_.start(ip, port);
std::cout << "HTTP Server started on http://" << ip << ":" << port << std::endl;
asio2::executor::run();
return true;
} catch (const std::exception& e) {
std::cerr << "Server start failed: " << e.what() << std::endl;
return false;
}
}
RouteManager& HttpServer::router() {
return router_;
}
void HttpServer::on_recv(TcpSession& session, std::string_view data) {
try {
HttpRequest req(data);
HttpResponse resp;
// 设置通用响应头
resp.set_header("Access-Control-Allow-Origin", "*");
resp.set_header("Server", "Asio2-Modular-HTTP-Server");
std::string method = req.method();
std::string path = req.path();
// 1. 优先匹配路由
if (router_.match(method, path, req, resp)) {
session.send(resp.buffer());
return;
}
// 2. 匹配静态文件请求(路径以 /static/ 开头)
if (path.starts_with("/static/") && static_manager_.handle(path, resp)) {
session.send(resp.buffer());
return;
}
// 3. 路由未匹配,返回 404
handle_404(resp);
session.send(resp.buffer());
} catch (const std::exception& e) {
// 捕获异常,返回 500
HttpResponse resp;
handle_500(resp);
session.send(resp.buffer());
std::cerr << "Request handle error: " << e.what() << std::endl;
}
}
void HttpServer::on_error(TcpSession& session, const boost::system::error_code& ec) {
if (ec) {
std::cerr << "Session error: " << ec.message() << " (client: " << session.remote_address() << ")" << std::endl;
}
}
void HttpServer::handle_404(HttpResponse& resp) {
resp.status(404, "Not Found");
resp.content_type("text/html; charset=utf-8");
resp.body("<h1>404 Not Found</h1><p>请求的资源不存在</p>");
}
void HttpServer::handle_500(HttpResponse& resp) {
resp.status(500, "Internal Server Error");
resp.content_type("text/html; charset=utf-8");
resp.body("<h1>500 Internal Server Error</h1><p>服务器内部错误</p>");
}
主函数 main.cpp(服务器启动与路由注册)
cpp
#include "http_server.h"
int main() {
// 1. 创建 HTTP 服务器实例
HttpServer server;
// 2. 获取路由管理器,注册路由
RouteManager& router = server.router();
// 3. 注册 GET 路由
// 3.1 根路径:欢迎页面
router.get("/", [](const HttpRequest& req, HttpResponse& resp) {
resp.status(200, "OK");
resp.content_type("text/html; charset=utf-8");
resp.body(R"(
<h1>Boost.Asio2 模块化 HTTP 服务器</h1>
<p>支持 GET/POST/静态文件/JSON 响应</p>
<ul>
<li><a href="/hello/Asio2">/hello/Asio2</a></li>
<li><a href="/api/json">/api/json</a></li>
<li><a href="/static/test.txt">/static/test.txt</a></li>
</ul>
)");
});
// 3.2 动态参数路由:/hello/xxx
router.get("/hello/:name", [](const HttpRequest& req, HttpResponse& resp) {
std::string name = req.path().substr(7); // 截取 /hello/ 后的参数
resp.status(200, "OK");
resp.content_type("text/plain; charset=utf-8");
resp.body("Hello, " + name + "!");
});
// 3.3 JSON 接口
router.get("/api/json", [](const HttpRequest& req, HttpResponse& resp) {
resp.status(200, "OK");
resp.content_type("application/json; charset=utf-8");
json data = {
{"code", 200},
{"message", "success"},
{"data", {
{"server_name", "Asio2-HTTP-Server"},
{"version", "2.0.0"},
{"method", req.method()}
}}
};
resp.body(data.dump(2)); // 格式化 JSON 输出
});
// 4. 注册 POST 路由
// 4.1 解析 JSON 格式的 POST 请求
router.post("/api/login", [](const HttpRequest& req, HttpResponse& resp) {
// 从请求体解析 JSON 数据
json req_body = json::parse(req.body());
std::string username = req_body.value("username", "");
std::string password = req_body.value("password", "");
// 模拟登录校验
json res_data;
if (username == "admin" && password == "123456") {
res_data = {{"code", 200}, {"message", "登录成功"}};
} else {
res_data = {{"code", 401}, {"message", "用户名或密码错误"}};
}
resp.status(200, "OK");
resp.content_type("application/json; charset=utf-8");
resp.body(res_data.dump());
});
// 4.2 解析表单格式的 POST 请求
router.post("/api/form", [](const HttpRequest& req, HttpResponse& resp) {
// asio2 内置解析表单数据(x-www-form-urlencoded)
std::string name = req.form_value("name");
std::string age = req.form_value("age");
resp.status(200, "OK");
resp.content_type("text/plain; charset=utf-8");
resp.body("Name: " + name + ", Age: " + age);
});
// 5. 启动服务器,监听 8080 端口
server.start("0.0.0.0", 8080);
return 0;
}
4.3.CMakeLists.txt(完整构建配置)
适配 VCPKG,支持条件编译 HTTPS,可直接复用:
cpp
cmake_minimum_required(VERSION 3.15)
project(asio2_http_server_modular)
# 配置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找依赖库
find_package(asio2 REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(OpenSSL REQUIRED) # HTTPS 依赖
# 创建可执行文件
add_executable(${PROJECT_NAME}
main.cpp
http_server.cpp
http_server.h
)
# 链接依赖库
target_link_libraries(${PROJECT_NAME} PRIVATE
asio2::asio2
nlohmann_json::nlohmann_json
OpenSSL::SSL
OpenSSL::Crypto
)
# 跨平台编译配置
if (WIN32)
# Windows 平台额外链接 ws2_32 库
target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32)
elseif (UNIX)
# Linux 平台额外链接 pthread 库
target_link_libraries(${PROJECT_NAME} PRIVATE pthread)
endif ()
4.4.编译运行
cpp
# 创建 build 目录
mkdir build && cd build
# Windows (Visual Studio 2022)
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE="D:/vcpkg/scripts/buildsystems/vcpkg.cmake"
cmake --build . --config Release
# Linux (GCC)
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake"
make -j4
# 运行服务器
./Release/asio2_http_server_modular.exe # Windows
./asio2_http_server_modular # Linux
4.5.功能测试
1.GET 请求测试
cpp
# 根路径
curl http://127.0.0.1:8080
# 动态参数路由
curl http://127.0.0.1:8080/hello/Asio2
# JSON 接口
curl http://127.0.0.1:8080/api/json
# 静态文件
curl http://127.0.0.1:8080/static/test.txt
2.POST 请求测试
cpp
# JSON 格式 POST(登录接口)
curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"123456"}' http://127.0.0.1:8080/api/login
# 表单格式 POST
curl -X POST -d "name=test&age=20" http://127.0.0.1:8080/api/form
3.错误场景测试
- 访问不存在的路径:
http://127.0.0.1:8080/404(返回 404) - 访问静态目录外的文件:
http://127.0.0.1:8080/static/../main.cpp(返回 404,路径穿越防护生效)
4.6.启用 HTTPS 服务
修改 HttpServer::start 方法,添加 SSL 配置(需准备证书文件 server.crt 和密钥 server.key):
cpp
bool HttpServer::start(const std::string& ip, uint16_t port) {
try {
// SSL 配置
server_.use_ssl("server.crt", "server.key");
server_.start(ip, port);
std::cout << "HTTPS Server started on https://" << ip << ":" << port << std::endl;
asio2::executor::run();
return true;
} catch (const std::exception& e) {
std::cerr << "Server start failed: " << e.what() << std::endl;
return false;
}
}
5.网络教程
基于c++和asio的网络编程框架asio2教程基础篇:1、基本概念和使用说明
开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,WEBSOCKET,RPC,ICMP,SSL,串口,跨平台,支持可靠UDP,支持TCP自动拆包等
使用asio2开发一个简易的http server
asio做tcp的自动拆包时,asio的match condition如何使用的详细说明
基于c++和asio的网络编程框架asio2教程基础篇:4、使用tcp客户端发送数据时,如何同步获取服务端返回结果
基于c++和asio的网络编程框架asio2教程使用篇:使用rpc模块编写rpc server和rpc client
rpc性能测试
关于asio2项目example目录中的几个tcp示例的说明
基于c++和asio的网络编程框架asio2教程基础篇:3、各个回调函数的触发线程以及多线程总结
基于c++和asio的网络编程框架asio2教程基础篇:2、各个回调函数的触发顺序和执行流程
6.与原生 Boost.Asio 的核心差异
- 接口复杂度 :Asio2 封装了
io_context、strand等底层对象,无需手动管理异步操作的线程安全。 - 功能集成:原生 Asio 需手动实现断线重连、心跳等功能,Asio2 已内置成熟方案。
- 兼容性:Asio2 可无缝调用原生 Asio 的接口,方便项目逐步迁移。