基于Beast的Http服务器基本流程
创始人
2024-11-15 03:03:30

Boost::Beast::Http服务器

命名空间和类型定义

namespace beast = boost::beast; namespace http = beast::http; namespace net = boost::asio; using tcp = boost::asio::ip::tcp; 

这些命名空间和类型定义简化了后续代码的书写。

命名空间 my_program_state

namespace my_program_state  { 	std::size_t request_count() 	{ 		static std::size_t count = 0; 		return ++count; 	}  	std::time_t now() 	{ 		return std::time(0); 	} } 

这个命名空间包含两个函数:

  • request_count():返回请求计数,每次调用时递增。
  • now():返回当前时间。

http_connection

这个类处理每个HTTP连接,继承自 std::enable_shared_from_this 以便在异步操作中安全地创建 shared_ptr

构造函数和 start 方法
http_connection(tcp::socket socket) 	: m_socket(std::move(socket)) { }  void start() { 	read_request(); 	check_deadline(); } 

构造函数接受一个TCP套接字。start 方法启动读取请求和超时检测。

私有成员变量
tcp::socket m_socket; beast::flat_buffer m_buffer{ 8192 }; http::request m_request; http::response m_response; net::steady_timer m_deadline{m_socket.get_executor(), std::chrono::seconds(60)}; 

这些成员变量包括套接字、缓冲区、请求和响应对象,以及一个超时定时器。

read_request 方法
void read_request() { 	auto self = shared_from_this(); 	http::async_read(m_socket, m_buffer, m_request, self { 		if (!ec) 		{ 			self->process_request(); 		} 	}); } 

这个方法异步读取HTTP请求,并在读取完成后调用 process_request 方法。

check_deadline 方法
void check_deadline() { 	auto self = shared_from_this(); 	m_deadline.async_wait(self { 		if (!ec) 		{ 			self->m_socket.close(ec); 		} 	}); } 

这个方法设置一个超时定时器,如果超时则关闭套接字。

process_request 方法
void process_request() { 	m_response.version(m_request.version()); 	m_response.keep_alive(false); 	switch (m_request.method()) 	{ 	case http::verb::get: 		m_response.result(http::status::ok); 		m_response.set(http::field::server, "Beast"); 		create_response(); 		break; 	case http::verb::post: 		m_response.result(http::status::ok); 		m_response.set(http::field::server, "Beast"); 		create_post_response(); 		break; 	default: 		m_response.result(http::status::bad_request); 		m_response.set(http::field::content_type, "text/plain"); 		beast::ostream(m_response.body()) << "Invalid request-method" << std::string(m_request.method_string()) << "`" << std::endl; 		break; 	} 	write_response(); } 

这个方法处理HTTP请求,根据请求方法生成响应。

create_response 方法
void create_response() { 	if (m_request.target() == "/count") 	{ 		m_response.set(http::field::content_type, "text/html"); 		beast::ostream(m_response.body()) 			<< "\n" 			<< "Request count\n" 			<< "\n" 			<< "

Request count

\n" << "

There have been " << my_program_state::request_count() << " requests so far.

\n" << "\n" << "\n"; } else if (m_request.target() == "/time") { m_response.set(http::field::content_type, "text/html"); beast::ostream(m_response.body()) << "\n" << "Current time\n" << "\n" << "

Current time

\n" << "

The current time is " << my_program_state::now() << " seconds since the epoch.

\n" << "\n" << "\n"; } else { m_response.result(http::status::not_found); m_response.set(http::field::content_type, "text/plain"); beast::ostream(m_response.body()) << "File not found\r\n"; } }

这个方法根据请求的目标生成不同的响应内容。

write_response 方法
void write_response() { 	auto self = shared_from_this(); 	m_response.content_length(m_response.body().size()); 	http::async_write(m_socket, m_response, self { 		self->m_socket.shutdown(tcp::socket::shutdown_send, ec); 		self->m_deadline.cancel(); 	}); } 

这个方法异步写入HTTP响应,并在完成后关闭套接字。

create_post_response 方法
void create_post_response() { 	if (m_request.target() == "/email") 	{ 		auto& body = this->m_request.body(); 		auto body_str = beast::buffers_to_string(body.data()); 		std::cout << "receive body is " << body_str << std::endl; 		this->m_response.set(http::field::content_type, "text/json"); 		Json::Value root; 		Json::Reader reader; 		Json::Value src_root; 		bool parse_success = reader.parse(body_str, src_root); 		if (!parse_success) 		{ 			std::cout << "Failed to parse Json data" << std::endl; 			root["error"] = 1001; 			std::string jsonstr = root.toStyledString(); 			beast::ostream(m_response.body()) << jsonstr; 			return; 		} 		auto email = src_root["email"].asString(); 		std::cout << "email is" << email << std::endl; 		root["error"] = 0; 		root["email"] = src_root["email"]; 		root["msg"] = "receive email post success"; 		std::string jsonstr = root.toStyledString(); 		beast::ostream(m_response.body()) << jsonstr; 	} 	else 	{ 		m_response.result(http::status::not_found); 		m_response.set(http::field::content_type, "text/plain"); 		beast::ostream(m_response.body()) << "File not found\r\n"; 	} } 

这个方法处理POST请求,解析JSON数据并生成响应。

方法概述

create_post_response 方法根据请求的目标路径处理POST请求。如果目标路径是 /email,则解析请求体中的JSON数据,并生成相应的响应。如果目标路径不是 /email,则返回404 Not Found响应。

代码解析
检查请求目标
if (m_request.target() == "/email")  

这行代码检查HTTP请求的目标路径是否为 /email

获取请求体
auto& body = this->m_request.body(); auto body_str = beast::buffers_to_string(body.data()); std::cout << "receive body is " << body_str << std::endl; 
  • auto& body = this->m_request.body(); 获取请求体的引用。
  • auto body_str = beast::buffers_to_string(body.data()); 将请求体转换为字符串。
  • std::cout << "receive body is " << body_str << std::endl; 打印接收到的请求体内容。
设置响应头
this->m_response.set(http::field::content_type, "text/json"); 

设置响应的内容类型为 text/json

解析JSON数据
Json::Value root; Json::Reader reader; Json::Value src_root; bool parse_success = reader.parse(body_str, src_root); if (!parse_success) { 	std::cout << "Failed to parse Json data" << std::endl; 	root["error"] = 1001; 	std::string jsonstr = root.toStyledString(); 	beast::ostream(m_response.body()) << jsonstr; 	return; } 
  • Json::Value root;Json::Value src_root; 定义两个JSON对象。
  • Json::Reader reader; 定义一个JSON解析器。
  • bool parse_success = reader.parse(body_str, src_root); 解析请求体中的JSON数据,并将结果存储在 src_root 中。
  • 如果解析失败,设置错误信息并返回响应。
处理解析后的数据
auto email = src_root["email"].asString(); std::cout << "email is" << email << std::endl; root["error"] = 0; root["email"] = src_root["email"]; root["msg"] = "receive email post success"; std::string jsonstr = root.toStyledString(); beast::ostream(m_response.body()) << jsonstr; 
  • auto email = src_root["email"].asString(); 获取解析后的JSON数据中的 email 字段。
  • 打印接收到的 email
  • 设置响应的JSON数据,包括 erroremailmsg 字段。
  • 将响应的JSON数据转换为字符串,并写入响应体。
处理未找到的目标路径
else { 	m_response.result(http::status::not_found); 	m_response.set(http::field::content_type, "text/plain"); 	beast::ostream(m_response.body()) << "File not found\r\n"; } 

如果请求的目标路径不是 /email,则返回404 Not Found响应,并设置响应体为 “File not found”。

总结

create_post_response 方法处理HTTP POST请求,解析请求体中的JSON数据,并生成相应的响应。如果请求的目标路径不是 /email,则返回404 Not Found响应。

http_server` 函数

void http_server(tcp::acceptor& acceptor, tcp::socket& socket) { 	acceptor.async_accept(socket, & { 		if (!ec) 		{ 			std::make_shared(std::move(socket))->start(); 		}  		http_server(acceptor, socket); 	}); } 

这个函数接受新的连接并创建 http_connection 对象来处理每个连接。

main 函数

int main() { 	try 	{ 		auto const address = net::ip::make_address("127.0.0.1"); 		unsigned short port = static_cast(8080); 		net::io_context ioc{1}; 		tcp::acceptor acceptor{ ioc,{address,port} }; 		tcp::socket socket{ ioc }; 		http_server(acceptor, socket); 		ioc.run(); 	} 	catch (const std::exception& e) 	{ 		std::cerr << "Error: " << e.what() << std::endl; 		return EXIT_FAILURE; 	} } 

这个函数设置服务器的IP地址和端口,创建 io_contextacceptorsocket,并启动服务器。

上一篇:花卉乐园项目详解

下一篇:yum安装软件

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...