基于moongoose的c++ http服务端


这只是一个半成品,仅有部分测试函数,需要根据自己的需要做一些修改和完善工作。
可以用作参考来实现一个轻量级的http服务端。

项目组成

在这里插入图片描述

头文件http_server.h

#ifndef HTTP_SERVER_H
#define HTTP_SERVER_H
#include <string>
#include <unordered_map>
#include <functional>
#include "mongoose.h"

// 定义http返回callback
typedef void OnRspCallback(mg_connection *c, std::string);
// 定义http请求handler
using ReqHandler = std::function<bool(std::string, std::string, mg_connection *c, OnRspCallback)>;

class HttpServer
{
public:
	HttpServer() {}
	~HttpServer() {}
	void Init(const std::string &port); // 初始化设置
	bool Start(); // 启动httpserver
	bool Close(); // 关闭
	void AddHandler(const std::string &url, ReqHandler req_handler); // 注册事件处理函数
	void RemoveHandler(const std::string &url); // 移除时间处理函数
	static std::string s_web_dir; // 网页根目录 
	static mg_serve_http_opts s_server_option; // web服务器选项
	static std::unordered_map<std::string, ReqHandler> s_handler_map; // 回调函数映射表

private:
	// 静态事件响应函数
	static void OnHttpEvent(mg_connection *connection, int event_type, void *event_data);
	static void HandleEvent(mg_connection *connection, http_message *http_req);
	static void SendRsp(mg_connection *connection, std::string rsp);

	std::string m_port;    // 端口
	mg_mgr m_mgr;          // 连接管理器
};
#endif

源文件http_control1.cpp

// http_control1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <memory>
#include "http_server.h"


// 初始化HttpServer静态类成员
mg_serve_http_opts HttpServer::s_server_option;
std::string HttpServer::s_web_dir = "./web";
std::unordered_map<std::string, ReqHandler> HttpServer::s_handler_map;


bool handle_fun1(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle fun1" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;

	rsp_callback(c, "rsp1");

	return true;
}

bool handle_fun2(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle fun2" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;

	rsp_callback(c, "rsp2");

	return true;
}
bool handle_fun3(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle fun3" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;
	char csSession_Key[100] = { 0 };
	mg_str m1;
	const char* pc1 = "session_key=DF9A3B1843A526AA&windfarm_ID=1000&windturbine_ID_List=1%23&cmd=parsed_data&data_Type_List=0&ts_Start=1531099800&ts_End=1531114200";
	int n1 = strlen(pc1);
	m1.p = c->recv_mbuf.buf;
	m1.len = c->recv_mbuf.len;
	m1.p = pc1;
	m1.len = n1;
	int nRes = mg_get_http_var(&m1, "session_key", csSession_Key, 100);
	const char* pcRes = "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}</string>";
	rsp_callback(c, pcRes);
	//SendRsp(connection, "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}</string>");
	return true;
}
bool handle_fun4(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle fun4" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;

	rsp_callback(c, "rsp4");

	return true;
}
bool handle_fun5(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle fun5" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;

	rsp_callback(c, "rsp5");

	return true;
}
bool GetSessionKey(std::string url, std::string body, mg_connection *c, OnRspCallback rsp_callback)
{
	// do sth
	std::cout << "handle GetSessionKey" << std::endl;
	std::cout << "url: " << url << std::endl;
	std::cout << "body: " << body << std::endl;
	const char* pcRes = "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"cms_vendor\":\"aa\",\"session_key\":\"DF9A3B1843A526AA\",\"key_alive_second\":3600}</string>";
	rsp_callback(c, pcRes);
  //rsp_callback(c, "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}</string>");


	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{

	std::string port = "7999";
	auto http_server = std::shared_ptr<HttpServer>(new HttpServer);
	http_server->Init(port);
	// add handler
	http_server->AddHandler("/api/fun1", handle_fun1);
	http_server->AddHandler("/api/fun2", handle_fun2);
	http_server->AddHandler("/api/GetCharacterData", handle_fun3);
	http_server->AddHandler("/api/fun4", handle_fun4);
	http_server->AddHandler("/api/fun5", handle_fun5);
	http_server->AddHandler("/api/GetSessionKey", GetSessionKey);
//	http_server->RemoveHandler("/api/fun6");
	// http_server->RemoveHandler("/api/fun3");
	http_server->Start();

	return 0;
}

源文件http_server.cpp

#include <utility>
#include "http_server.h"

void HttpServer::Init(const std::string &port)
{
	m_port = port;
	s_server_option.enable_directory_listing = "yes";
	s_server_option.document_root = s_web_dir.c_str();
	// TODO:其他设置
}

bool HttpServer::Start()
{
	mg_mgr_init(&m_mgr, NULL);
	mg_connection *connection = mg_bind(&m_mgr, m_port.c_str(), OnHttpEvent);
	if (connection == NULL)
		return false;
	mg_set_protocol_http_websocket(connection);

	printf("starting http server at port: %s\n", m_port.c_str());
	// loop
	while (true)
		mg_mgr_poll(&m_mgr, 500); // ms

	return true;
}

void HttpServer::OnHttpEvent(mg_connection *connection, int event_type, void *event_data)
{
	http_message *http_req = (http_message *)event_data;
	switch (event_type)
	{
	case MG_EV_HTTP_REQUEST:
	//case 0:
		HandleEvent(connection, http_req);
		break;
	default:
		break;
	}
}

static bool route_check(http_message *http_msg, char *route_prefix)
{
	if (mg_vcmp(&http_msg->uri, route_prefix) == 0)
		return true;
	else
		return false;

	// TODO: 还可以判断 GET, POST, PUT, DELTE等方法
	//mg_vcmp(&http_msg->method, "GET");
	//mg_vcmp(&http_msg->method, "POST");
	//mg_vcmp(&http_msg->method, "PUT");
	//mg_vcmp(&http_msg->method, "DELETE");
}

void HttpServer::AddHandler(const std::string &url, ReqHandler req_handler)
{
	if (s_handler_map.find(url) != s_handler_map.end())
		return;

	s_handler_map.insert(std::make_pair(url, req_handler));
}

void HttpServer::RemoveHandler(const std::string &url)
{
	auto it = s_handler_map.find(url);
	if (it != s_handler_map.end())
		s_handler_map.erase(it);
}

void HttpServer::SendRsp(mg_connection *connection, std::string rsp)
{
	// 必须先发送header
	mg_printf(connection, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
	// 以json形式返回
	//mg_printf_http_chunk(connection, "{ \"result\": %s }", rsp.c_str());
	mg_printf_http_chunk(connection, "%s", rsp.c_str());
	// 发送空白字符快,结束当前响应
	mg_send_http_chunk(connection, "", 0);
}

void HttpServer::HandleEvent(mg_connection *connection, http_message *http_req)
{
	std::string req_str = std::string(http_req->message.p, http_req->message.len);
	printf("got request: %s\n", req_str.c_str());

	// 先过滤是否已注册的函数回调
	std::string url = std::string(http_req->uri.p, http_req->uri.len);
	std::string body = std::string(http_req->body.p, http_req->body.len);
	auto it = s_handler_map.find(url);
	if (it != s_handler_map.end())
	{
		ReqHandler handle_func = it->second;
		handle_func(url, body, connection, SendRsp);
	}

	// 其他请求
	if (route_check(http_req, "/")) // index page
		mg_serve_http(connection, http_req, s_server_option);
	else if (route_check(http_req, "/api/hello"))
	{
		// 直接回传
		SendRsp(connection, "welcome to httpserver");
	}
	else if (route_check(http_req, "/api/sum"))
	{
		// 简单post请求,加法运算测试
		char n1[100], n2[100];
		double result;

		/* Get form variables */
		mg_get_http_var(&http_req->body, "n1", n1, sizeof(n1));
		mg_get_http_var(&http_req->body, "n2", n2, sizeof(n2));

		/* Compute the result and send it back as a JSON object */
		result = strtod(n1, NULL) + strtod(n2, NULL);
		SendRsp(connection, std::to_string(result));
	}
	else if (route_check(http_req, "/api/GetCharacterData"))//GetCharacterData
	{
		/*SendRsp(connection, "<?xml version=\"1.0\"encoding=\"utf-8\"?>"
			"<string xmlns=\"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}< / string>"
			);*/
		SendRsp(connection, "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}</string>"
			);
	}
	else if (route_check(http_req, "/api/GetWaveFormData"))//GetWaveFormData
	{
		SendRsp(connection, "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\", \"windfram_id\" : 1000, \"windTurbine_id_list\" : \"1#\", \"data_list\" : []}</string>"
			);
	}
	else if (route_check(http_req, "/api/GetAlarmrData"))//GetAlarmrData
	{
		SendRsp(connection, "<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns = \"http://tempuri.org/\">{\"status\":\"OK\",\"windfarm_id\":1000,\"windturbine_id_list\":\"1#\",\"data_type_list\" : []}</string>"
			);
	}
	else
	{
		mg_printf(
			connection,
			"%s",
			"HTTP/1.1 501 Not Implemented\r\n"
			"Content-Length: 0\r\n\r\n");
	}
}

bool HttpServer::Close()
{
	mg_mgr_free(&m_mgr);
	return true;
}

我记得参考过一篇博客,但是实在找不到了,只有工程里的代码,如有人自认原作者请与我联系

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用Boost库来实现一个基于C++的Linux HTTP服务器。以下是一个简单的示例代码: ```cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> class HttpServer { public: HttpServer(boost::asio::io_service& ioService, short port) : acceptor_(ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { startAccept(); } private: void startAccept() { boost::asio::ip::tcp::socket socket(acceptor_.get_io_service()); acceptor_.async_accept(socket, boost::bind(&HttpServer::handleAccept, this, socket, boost::asio::placeholders::error)); } void handleAccept(boost::asio::ip::tcp::socket& socket, const boost::system::error_code& error) { if (!error) { std::cout << "Accepted connection from: " << socket.remote_endpoint().address().to_string() << std::endl; startAccept(); } } boost::asio::ip::tcp::acceptor acceptor_; }; int main() { boost::asio::io_service ioService; HttpServer server(ioService, 8080); ioService.run(); return 0; } ``` 这个简单的HTTP服务器使用Boost库中的`asio`模块来处理网络通信。它监听8080端口,并在有新连接时打印客户端的IP地址。你可以根据需要扩展这个示例,添加HTTP请求处理逻辑。 请注意,这只是一个基本的示例,实际的HTTP服务器可能需要更多的功能和复杂性。你可能需要处理HTTP请求、路由、静态文件服务、动态内容生成等。但是,这个示例应该可以帮助你入门并了解如何使用Boost库构建一个简单的Linux C++ HTTP服务器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值