基于 Boost.Asio 和 Boost.Beast 的异步 HTTP 服务器(学习记录)

已完成功能:

支持 GETPOST 请求的路由与回调处理。

解析URL请求。

单例模式 管理核心业务逻辑。

异步 I/O 技术和 定时器 控制超时。

通过回调函数注册机制,可以灵活地为不同的 URL 路由注册处理函数。

1. 项目背景

1.1 项目简介

本项目是一个基于 Boost.AsioBoost.Beast 的高性能 HTTP 服务器,实现了对 HTTP 请求的处理、路由功能和回调机制。该服务器使用 单例模式 来管理请求逻辑,并采用 异步 I/O 技术 来提升并发处理能力。支持的 HTTP 请求类型包括 GETPOST,并能够根据 URL 注册不同的处理函数,从而实现灵活的请求路由与回调处理机制。

1.2 项目目标

该项目旨在提供一个 高效可扩展 的 HTTP 服务器,适用于处理大量并发 HTTP 请求,具备以下核心目标:

  • 高并发处理能力:通过使用异步 I/O 和非阻塞 I/O 操作显著提升并发处理能力,避免因同步阻塞导致的性能瓶颈。
  • 可扩展性:支持通过注册回调函数来灵活处理不同的 HTTP 请求,能够根据需要扩展支持更多的 HTTP 请求类型和自定义业务逻辑。
  • 简洁的单例管理:使用单例模式管理全局资源,确保只有一个服务器实例和唯一的请求逻辑处理实例,避免重复初始化资源和管理多个实例的问题。
  • 超时管理 :通过 Boost.Asio 提供的定时器机制实现 HTTP 连接的超时控制,确保服务器能够及时关闭不活跃的连接,避免因连接泄漏导致的资源浪费。

2. 项目架构

2.1 架构概述

本项目采用了事件驱动的架构模型,基于 Boost.Asio 提供的异步 I/O 功能实现高效的请求处理。整个系统通过 CServer 启动并接受客户端的连接,HttpConnection 管理每个 HTTP 请求的连接,LogicSystem 处理请求的业务逻辑,利用 单例模式 确保请求处理逻辑的唯一性。各个模块协同工作,通过回调机制对请求进行处理。

服务器架构可以分为以下几个关键模块:

  • CServer:负责启动服务器,监听指定端口并接受客户端连接请求。
  • LogicSystem:使用单例模式管理 HTTP 请求的逻辑处理,负责路由注册与回调函数的执行。
  • HttpConnection:处理每个 HTTP 请求的连接,包括请求解析、响应构建以及连接超时管理。
  • Singleton:一个模板类,提供单例模式的实现,确保系统中逻辑处理系统和其他核心组件只有一个实例。
  • 回调函数 :通过回调函数类型 HttpHandler 处理 HTTP 请求,支持 GET 和 POST 请求的灵活处理。

2.2 模块划分

1.网络通信模块

该模块基于 Boost.Asio 库实现,用于管理异步的 TCP 连接和 HTTP 请求的处理。CServer 负责监听端口并接受客户端连接,HttpConnection 负责处理每个连接的 HTTP 请求,采用非阻塞 I/O 操作来保证服务器的高效性能。

关键类:

  • CServer :负责创建 acceptor 并等待连接,管理 tcp::socket
  • HttpConnection:负责处理 HTTP 请求和响应,管理 TCP 连接。
2.HTTP 请求处理模块

该模块基于 Boost.Beast 实现,负责解析 HTTP 请求和构建 HTTP 响应。使用 http::requesthttp::response 类型来处理请求和响应内容。该模块还通过回调函数 HttpHandler 进行路由处理。

关键类:

  • HttpConnection:解析请求并构建响应。
  • LogicSystem:注册并调用处理 GET/POST 请求的回调函数。
3.单例模式模块

通过模板实现的 Singleton 类,确保了系统中 LogicSystem 类等重要组件的唯一性。它通过懒汉式单例模式来延迟初始化,避免了不必要的资源浪费,确保系统的高效运行。

关键类:

  • Singleton :模板类,用于实现 LogicSystem 等核心组件的单例模式。
4.超时管理模块

Boost.Asiosteady_timer 被用于处理连接超时。每个 HTTP 连接都配备了一个定时器,如果连接在规定时间内没有收到有效响应,则会自动关闭连接,防止资源泄漏。

关键类:

  • HttpConnection :内部持有一个 steady_timer,用于处理每个连接的超时。

2.3 数据流

项目的数据流过程如下:

  1. CServer 启动并监听指定端口,等待来自客户端的 TCP 连接。
  2. 客户端连接请求到来时,CServer 使用 acceptor 接受连接,并为每个连接创建一个 HttpConnection 实例。
  3. HttpConnection 启动异步读取操作,接收客户端发送的 HTTP 请求,并将请求数据存储在 beast::flat_buffer 中。
  4. 在接收到完整的 HTTP 请求后,HttpConnection 会解析请求,提取 URL 和请求方法(如 GET 或 POST)。
  5. HttpConnection 将请求转交给 LogicSystemLogicSystem 根据请求的 URL 查找对应的回调函数(HttpHandler),并执行该回调函数进行处理。
  6. 回调函数处理完请求后,HttpConnection 将生成相应的 HTTP 响应,并异步将响应数据发送回客户端。
  7. 如果连接在规定时间内未完成处理,HttpConnection 会触发定时器,主动关闭连接,避免资源浪费。

3. 模块详细设计

由于代码太长,源码我给出链接

源码下载地址,密码:bhmyhttps://wwta.lanzoue.com/iqugu2k8shij

3.1 CServer 模块

CServer 类是整个 HTTP 服务器的入口,负责启动服务器,监听并接受来自客户端的连接。它依赖于 Boost.Asio 库提供的 tcp::acceptor 来监听指定的端口。当客户端连接到服务器时,CServer 会为每个连接创建一个新的 HttpConnection 对象来处理该连接。

关键函数:
  • Start():启动服务器并开始接受客户端连接。
  • Accept() :异步接受客户端连接,当有新的连接请求时调用 HttpConnection 来处理。

CServer 的主要任务是创建和管理连接,每当有新的连接请求时,它会为该连接创建一个 HttpConnection 对象,后者将负责处理 HTTP 请求。

cpp 复制代码
#ifndef CSERVER_H
#define CSERVER_H
#include "const.h"

// CServer 类,负责接受客户端连接并处理连接请求
class CServer :public std::enable_shared_from_this<CServer> {
public:
	CServer(boost::asio::io_context& ioc, unsigned short& port);// 构造函数:初始化服务器并绑定到指定端口
	void Start(); // 启动服务器,开始接受连接
private:
	tcp::acceptor _acceptor;// 用于接受 TCP 连接的接受器
	net::io_context& _ioc;// 提供 I/O 服务的上下文对象
	tcp::socket _socket;// 用于与客户端通信的套接字
};
#endif

3.2 HttpConnection 模块

HttpConnection 类管理每一个客户端的 HTTP 连接。它负责异步读取客户端请求,解析 HTTP 请求,查找 URL 对应的回调函数,并生成 HTTP 响应返回给客户端。此外,HttpConnection 还负责超时管理,通过 Boost.Asiosteady_timer 来确保每个连接的生命周期不会过长,从而避免资源泄漏。

关键函数:
  • Start():启动连接,开始处理 HTTP 请求。
  • HandleReq():处理 HTTP 请求,包括解析请求内容并根据请求方法调用相应的回调函数。
  • CheckDeadline():检查当前连接是否超时,超时则关闭连接。
  • WriteResponse():将生成的 HTTP 响应数据写入客户端。

HttpConnection 的任务是在接收到请求后,解析出请求的方法(GET/POST)、URL 和参数,并将其传递给 LogicSystem 来进行后续的处理。最终,将服务器的响应发送给客户端。

cpp 复制代码
#ifndef HTTPCONNECTION_H
#define HTTPCONNECTION_H
#include "const.h"

// HttpConnection 类,负责与客户端的 HTTP 连接
// 提供处理 HTTP 请求、定时器管理等功能
class HttpConnection :public std::enable_shared_from_this<HttpConnection> {
	friend class LogicSystem;// 允许 LogicSystem 访问 HttpConnection 的私有成员
public:
	HttpConnection(tcp::socket socket);// 构造函数:接受 TCP 套接字,初始化连接
	void Start(); // 启动连接处理
private:
	void CheckDeadline();// 检查是否超时,定时器功能
	void WriteResponse();// 写入响应数据
	void HandleReq(); // 处理 HTTP 请求
	void PreParseGetParam();//处理参数解析
	tcp::socket _socket;// 客户端套接字
	beast::flat_buffer _buffer{ 8192 };// 接收数据的缓冲区,最大缓存 8192 字节
	http::request<http::dynamic_body> _request;// HTTP 请求对象,存储接收到的 HTTP 请求数据
	http::response<http::dynamic_body> _response;// HTTP 响应对象,存储响应数据并发送给客户端
	// 定时器,检查连接是否超时,60 秒后自动关闭连接
	net::steady_timer deadline_{
		_socket.get_executor(),std::chrono::seconds(60)
	};
	std::string _get_url; // 存储请求的 URL
	std::unordered_map<std::string, std::string> _get_params;// 存储 GET 请求的查询参数,以键值对形式存储
};

#endif

3.3 LogicSystem 模块

LogicSystem 类是整个系统的核心,负责管理 HTTP 请求的路由与回调函数。它采用 单例模式 确保系统中只有一个逻辑处理实例,并通过 std::map 存储 GET 和 POST 请求的回调函数。每当 HTTP 请求到来时,HttpConnection 会将请求的 URL 传递给 LogicSystem,然后根据请求方法(GET/POST)查找并执行对应的回调函数。

关键函数:
  • RegGet():注册 GET 请求的回调函数。
  • RegPost():注册 POST 请求的回调函数。
  • HandleGet():处理 GET 请求,执行对应的回调函数。
  • HandlePost():处理 POST 请求,执行对应的回调函数。

LogicSystem 是一个单例类,它为每个请求类型(GET/POST)提供了 URL 到回调函数的映射表。当请求到来时,LogicSystem 会根据请求的 URL 查找相应的回调函数并执行,从而实现不同 URL 对应不同的处理逻辑。

cpp 复制代码
#ifndef LOGICSYSTEM_H
#define LOGICSTSTEM_H
#include "Singleton.h"
#include <functional>
#include <map>
#include "const.h"

class HttpConnection;

typedef std::function<void(std::shared_ptr<HttpConnection>)> HttpHandler;// 定义一个回调函数类型,处理 HTTP 请求
// HttpHandler 通过 shared_ptr 传递 HttpConnection 对象

// LogicSystem 类,用于管理 HTTP 请求的逻辑处理
// 采用单例模式,确保系统只有一个实例
class LogicSystem : public Singleton<LogicSystem> {
	friend class Singleton<LogicSystem>; // 允许 Singleton 类访问 LogicSystem 的构造函数
public:
	~LogicSystem();// 析构函数,负责释放资源
	bool HandleGet(std::string path, std::shared_ptr<HttpConnection> con); // 处理GET请求的函数
	bool HandlePost(std::string path, std::shared_ptr<HttpConnection> con);//处理POST请求的函数
	void RegGet(std::string url, HttpHandler handler);// 注册 GET 请求的回调函数
	void RegPost(std::string url, HttpHandler handler);// 注册POST请求的回调函数
private:
	LogicSystem(); // 构造函数,私有化以防外部直接创建实例
	//key为路由,value为回调函数
	std::map<std::string, HttpHandler> _post_handlers; // 存储 POST 请求的处理函数
	std::map<std::string, HttpHandler> _get_handlers; // 存储 GET 请求的处理函数
};
#endif

3.4 Singleton 模块

Singleton 模块通过模板实现了单例模式,确保系统中的核心组件(如 LogicSystem)只有一个实例。该模板类使用懒汉式初始化,确保在首次访问时才创建实例,并且每次访问都返回同一个实例。

关键函数:
  • GetInstance():获取单例实例,如果实例尚未创建,则进行初始化。
  • PrintAddress():打印当前单例实例的地址,便于调试。

Singleton 模块保证了系统中只有一个实例,可以有效避免重复实例化带来的资源浪费。通过使用 std::shared_ptr 管理实例的生命周期,确保实例的销毁是在所有引用都释放后进行的。

cpp 复制代码
#ifndef SINGLETON_H
#define SINGLETON_H
#include <mutex>
#include <iostream>
#include <memory>

// Singleton 模板类,确保一个类只有一个实例
// 使用 std::shared_ptr 来管理实例生命周期
template <typename T>
class Singleton {
protected:
	Singleton() = default;  // 默认构造函数,防止外部实例化
	Singleton(const Singleton<T>&) = delete; // 禁止拷贝构造
	Singleton& operator=(const Singleton<T>& st) = delete; // 禁止拷贝赋值

	static std::shared_ptr<T> _instance;// 存储单例实例的静态变量
public:
	// 获取单例实例,线程安全的懒汉式初始化
	static std::shared_ptr<T> GetInstance() {
		static std::once_flag s_flag;// 用于确保单例实例只被创建一次
		std::call_once(s_flag, [&]() {
			// 创建单例实例并保存在 _instance 中
			_instance = std::shared_ptr<T>(new T);
			});
		return _instance;// 返回单例实例
	}
	// 打印当前单例实例的地址
	void PrintAddress() {
		std::cout << _instance.get() << std::endl;
	}
	// 析构函数,打印销毁信息
	~Singleton() {
		std::cout << "this is singleton destruct" << std::endl;
	}
};

// 为单例提供静态变量的初始化
template<typename T>
std::shared_ptr<T>Singleton<T>::_instance = nullptr;
#endif

4.测试

输入http://localhost:8080/get_test

显示receive get_test req

输入http://localhost:8080/get_test?key1=value1&key2=value2

显示

复制代码
receive get_test req
param1key iskey1, value isvalue1
param2key iskey2, value isvalue2 
相关推荐
晚风_END2 小时前
node.js|浏览器插件|Open-Multiple-URLs的部署和使用,实现一键打开多个URL的强大工具
服务器·开发语言·数据库·node.js·dubbo
姜太小白3 小时前
【Nginx】设置https和http同时使用同一个端口访问
nginx·http·https
迷茫的小技术4 小时前
OSPF使能配置
运维·服务器·网络
云计算DevOps-韩老师5 小时前
【网络云SRE运维开发】2025第2周-每日【2025/01/07】小测-【第7章 GVRP链路捆绑】理论和实操
服务器·网络·计算机网络·云计算·运维开发
码力全開5 小时前
C 语言奇幻之旅 - 第14篇:C 语言高级主题
服务器·c语言·开发语言·人工智能·算法
小学导航员5 小时前
centos服务器 /1ib64/libm.so.6: version “GLIBc 2.27’ not found 异常
linux·服务器·centos
揽星逐月酒微醺6 小时前
find 查找文件grep匹配数据
linux·运维·服务器
银河麒麟操作系统6 小时前
【银河麒麟高级服务器操作系统】服务器异常重启故障分析及处理建议
linux·运维·服务器·安全·电脑
Codeking__6 小时前
Linux初识——基本指令
linux·运维·服务器
sun0077006 小时前
Linux如何查看有多少个用户登录?
linux·运维·服务器