httpserver:
包含内容:C++ 、mongoose、http协议
此次只实现了服务端,客户端没有去实现。最终测试成功
主要针对客户端使用POST方式进行应答,GET方式也可以
客户端使用POST方式上传的信息会通过标准输出函数输出在终端上
代码:
main.cpp
// *************************************************
// File name: main.cpp
// Author: xhp
// Version: 1.0
// Date: 2021/7/21
// Description: C++利用mongoose实现http服务端
// *************************************************
#include
#include "./http/http_server.h"
//初始化HttpServer静态类成员
std::string HttpServer::s_web_dir = "."; //当前目录
bool HttpServer::compare_flag = true; //默认将响应体判断结果设成 true
mg_serve_http_opts HttpServer::s_server_option;
std::unordered_map<std::string,ReqHandler> HttpServer::s_handler_map;
/**
* @Description:http应答信息输出函数
* @param Req_message: 返回的信息字符串
* @param c: mg_connection结构体定义的指针(mongoose connection)
* @param rsp_callback: 向服务端返回应答信息的函数指针
* @return none
*/
bool handle_function(std::string Req_message,mg_connection *c,OnRspCallback rsp_callback)
{
//do sth
std::cout<<Req_message<<"\n"<<std::endl; //输出http请求信息(请求行+消息报头+请求正文)
rsp_callback(c); //返回应答信息 "code=0000" 表示成功,其他表示失败
return true;
}
int main(int argc,char *argv[])
{
std::string port; //创建一个string类型的端口
auto http_server = std::shared_ptr<HttpServer>(new HttpServer); //创建一个智能指针
std::cout<<"please input port number : ";
std::cin>>port;
http_server->Init(port);
http_server->AddHandler("/",handle_function);
http_server->Start();
return 0;
}
http_server.cpp
// *************************************************
// File name: http_server.cpp
// Author: xhp
// Version: 1.0
// Date: 2021/7/21
// Description: C++利用mongoose实现http服务端
// *************************************************
#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(); //c_str()将string类型的字符串以char*类型返回
}
/**
* @Description:启动httpserver
* @param none
* @return 成功: true ,失败: false
*/
bool HttpServer::Start()
{
mg_mgr_init(&m_mgr,NULL); // 初始化mongoose manager
mg_connection *connection = mg_bind(&m_mgr,m_port.c_str(),HttpServer::OnHttpEvent);
if(connection == NULL)
return false;
mg_set_protocol_http_websocket(connection); //调用此函数将上一步返回给connection的数据与内建的http handler绑定
//这样我们的handler才能收到http事件
printf("starting http server at port : %s , ready !!!\n\n",m_port.c_str());
while(HttpServer::compare_flag)
mg_mgr_poll(&m_mgr,500); //ms 通过一直调用mg_mgr_poll接收请求
std::cout<<"error : respond format error!\n"<<std::endl; //compare_flag标志位被置为false,表示响应体格式不合规定
Close(); //关闭并释放所有活动的连接
return true;
}
/**
* @Description:事件响应函数
* @param connection: mongoose connection
* @param event_type: 事件类型
* @param event_data: 事件数据
* @return none
*/
void HttpServer::OnHttpEvent(mg_connection *connection,int event_type,void *event_data)
{
if(event_type == MG_EV_HTTP_REQUEST) {
http_message *http_req = (http_message *)event_data;
HandleHttpEvent(connection,http_req);
}
}
/**
* @Description:路径检查函数
* @param http_msg: 关于HTTP请求的一些信息,http_message是一个HTTP协议存储有关信息的结构体
* @param route_prefix: 指定的资源定位符(url)
* @return 成功: true ,失败: false
*/
static bool route_check(const http_message *http_msg,const char *route_prefix)
{
if(mg_vcmp(&http_msg->uri,route_prefix) == 0) // http_msg->uri --> "/my_file.html"
return true;
else
return false;
}
/**
* @Description:处理http事件
* @param connection: mongoose connection
* @param http_req: 关于HTTP请求的一些信息,http_message是一个HTTP协议存储有关信息的结构体
* @return none
*/
void HttpServer::HandleHttpEvent(mg_connection *connection, http_message *http_req)
{
std::string req_str = std::string(http_req->message.p,http_req->message.len);//截取前http_req->message.len长度的字符串
//先过滤是否已注册的函数回调
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);
if(strncmp(body.c_str(),"vgdecoderesult",sizeof("vgdecoderesult")-1) == 0)
HttpServer::compare_flag = true;
else
HttpServer::compare_flag = false;
auto it = s_handler_map.find(url); //在s_handler_map中寻找url,将结果返回给it,如果没有找到,就返回s_handler_map.end()
if(it != s_handler_map.end()) {
ReqHandler handler_func = it->second; //second指向handler_funcation,每个url对应一个单独的second
handler_func(req_str.c_str(),connection,&HttpServer::SendHttpRsp);//这个handler_func在调用handler_function函数
}
//其他请求
if(route_check(http_req,(char*)"/")) //url比较
mg_serve_http(connection,http_req,s_server_option);
else {
mg_printf(
connection,
"%s",
"HTTP/1.1 501 Not Implemented",
"Content-Length: 0\r\n\r\n"
);
}
}
/**
* @Description: http respond
* @param connection: mongoose connection
* @return none
*/
void HttpServer::SendHttpRsp(mg_connection *connection)
{
if(HttpServer::compare_flag == true){
//告诉设备,0000表示成功,1111表示失败
mg_printf(connection, "%s",
"HTTP/1.1 200 OK code=0000\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Content-Length: 0\r\n\r\n"
);
mg_printf_http_chunk(connection, "{ \"result\": %s }", "code=0000");// 以json形式返回
}
else if(HttpServer::compare_flag == false){
mg_printf(connection, "%s",
"HTTP/1.1 200 OK code=1111\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Content-Length: 0\r\n\r\n"
);
mg_printf_http_chunk(connection, "{ \"result\": %s }", "code=1111");// 以json形式返回
}
mg_send_http_chunk(connection,"",0); // 发送空白字符块,结束当前响应
}
/**
* @Description: free memory
* @param none
* @return true
*/
bool HttpServer::Close()
{
mg_mgr_free(&m_mgr);
return true;
}
/**
* @Description: add Handler
* @param url: 资源定位符
* @param req_handler: 事件处理函数指针
* @return none
*/
void HttpServer::AddHandler(const std::string &url,ReqHandler req_handler)
{
if(s_handler_map.find(url) != s_handler_map.end()) //找到了url(统一资源定位符),就return出去
return;
s_handler_map.insert(std::make_pair(url,req_handler)); //没找到这个url,就把url插入进去
//make_pair函数是将url和req_handler进行处理后将返回值插入进s_handler_map
}
http_server.h
#pragma once
#include "../mongoose/mongoose.h"
#include
#include
#include
#include
#include
#include
//定义http返回callback
typedef void OnRspCallback(mg_connection *c);
//定义http请求handler
using ReqHandler = std::function<bool (std::string,mg_connection *c,OnRspCallback)>; //ReqHandler用来保存function返回的一个函数指针
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); //注册时间处理函数
static mg_serve_http_opts s_server_option; //web服务器选项
static std::string s_web_dir; //网页根目录
static bool compare_flag; //判断响应体内容是否符合要求
static std::unordered_map<std::string,ReqHandler> s_handler_map; //回调函数映射表
//unordered_map 无序关联式容器
//map和unordered_map唯一的区别就是map是有序存储的,
//而unordered_map是无序存储的
private:
static void SendHttpRsp(mg_connection *connection); //服务端向客户端发送http响应
static void HandleHttpEvent(mg_connection *connection, http_message *http_req); //处理http事件
static void OnHttpEvent(mg_connection *connection,int event_type,void *event_data); //事件响应函数
std::string m_port; //端口
mg_mgr m_mgr; //连接管理器
};