IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 实现 httpserver (mongoose) -> 正文阅读

[C++知识库]C++ 实现 httpserver (mongoose)

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 <memory>
#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 <string>
#include <string.h>
#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <iostream>

//定义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;                                                                       //连接管理器
};
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 23:54:43  更:2021-07-24 23:55:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 11:21:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码