Asio2: 一个基于 Boost.Asio 封装的高性能网络编程库

目录

1.简介

[2.安装方式(适配 CMake/VCPKG)](#2.安装方式(适配 CMake/VCPKG))

[3.核心 API 与使用示例](#3.核心 API 与使用示例)

[4.HTTP 服务器超详细示例](#4.HTTP 服务器超详细示例)

4.1.服务器架构设计

4.2.完整源代码(分文件组织)

4.3.CMakeLists.txt(完整构建配置)

4.4.编译运行

4.5.功能测试

[4.6.启用 HTTPS 服务](#4.6.启用 HTTPS 服务)

5.网络教程

[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)

vcpkg: 一款免费开源的C++包管理器

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.服务器架构设计

采用模块化拆分,避免回调地狱,核心模块如下:

  1. 路由管理器:统一管理 GET/POST 路由,支持路径匹配
  2. 请求处理器:解析 GET 参数、POST 表单 / JSON 数据
  3. 静态文件管理器:处理静态资源请求,支持文件类型映射
  4. 响应构造器:统一封装 HTTP 响应(状态码、响应头、响应体)
  5. 错误处理器:捕获并返回 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_contextstrand 等底层对象,无需手动管理异步操作的线程安全。
  • 功能集成:原生 Asio 需手动实现断线重连、心跳等功能,Asio2 已内置成熟方案。
  • 兼容性:Asio2 可无缝调用原生 Asio 的接口,方便项目逐步迁移。
相关推荐
gcfer35 分钟前
CS144 中的C++知识积累
c++·右值引用·智能指针·optional容器
牛奶咖啡131 小时前
解决配置虚拟网络后同网段的设备网络不通问题
网络·桥接模式·主机模式·配置虚拟网络后同网段设备不通·排查解决同网段同网关网络不通·重置windows主机网络·nas模式
Bona Sun2 小时前
单片机手搓掌上游戏机(二十)—pico运行doom之编译环境
c语言·c++·单片机·游戏机
车载测试工程师2 小时前
CAPL学习-ETH功能函数-通用函数
网络·学习·tcp/ip·capl·canoe
ICT技术最前线2 小时前
sdwan组网软件如何帮助企业提升网络效率?
网络·sdwan·宽带组网
Albert Edison2 小时前
【项目设计】C++ 高并发内存池
数据结构·c++·单例模式·哈希算法·高并发
我真不会起名字啊2 小时前
C、C++中的sprintf和stringstream的使用
java·c语言·c++
猿饵块3 小时前
ros2--图像/image
c++
老蒋新思维3 小时前
创客匠人洞察:AI 时代 IP 变现的认知重构,从流量焦虑到价值深耕的破局之道
网络·人工智能·tcp/ip·重构·知识付费·创始人ip·创客匠人