当前位置: 首页 > news >正文

Mongoose http server 例子

        今天抽了点时间看了一下 mongoose的源码, github 地址,发现跟以前公司内部使用的不太一样,这里正好利用其 http server 例子来看一下。以前的 http message 结构体是这样的:

/* HTTP message */
struct http_message {struct mg_str message; /* Whole message: request line + headers + body */struct mg_str body;    /* Message body. 0-length for requests with no body *//* HTTP Request line (or HTTP response line) */struct mg_str method; /* "GET" */struct mg_str uri;    /* "/my_file.html" */struct mg_str proto;  /* "HTTP/1.1" -- for both request and response *//* For responses, code and response status message are set */int resp_code;struct mg_str resp_status_msg;/** Query-string part of the URI. For example, for HTTP request*    GET /foo/bar?param1=val1&param2=val2*    |    uri    |     query_string     |** Note that question mark character doesn't belong neither to the uri,* nor to the query_string*/struct mg_str query_string;/* Headers */struct mg_str header_names[MG_MAX_HTTP_HEADERS];struct mg_str header_values[MG_MAX_HTTP_HEADERS];
};

github 上的源码的http message 结构体是这样的:

struct mg_http_message {struct mg_str method, uri, query, proto;             // Request/response linestruct mg_http_header headers[MG_MAX_HTTP_HEADERS];  // Headersstruct mg_str body;                                  // Bodystruct mg_str head;                                  // Request + headersstruct mg_str chunk;    // Chunk for chunked encoding,  or partial bodystruct mg_str message;  // Request + headers + body
};

很明显现在的头部消息使用了 mg_http_header 结构体,它的定义是这样的:

struct mg_http_header {struct mg_str name;   // Header namestruct mg_str value;  // Header value
};

今天使用的是mongoose 自带的例子,位于源码目录的 examples/http-server 下的 main.c,因为我使用了c++的,所以我自己创建了目录 myExample/http_server,把它的 main.c 换成了 main.cpp,makefile 使用自己的,在编译的时候解决一下编译问题即可。

自己写的Makefile

#中间文件存放目录,如.o 和 .d 文件
COMPILE_DIR = compile
BIN_DIR = bin# 可编译arm版本
#CROSS = arm-himix200-linux-
CC = gcc 
CPP = $(CROSS)g++ -std=c++11
CFLAGS = -Werror -g
CFLAGS += -I../../
CPP_SRCS = $(wildcard *.cpp)
CPP_OBJS = $(patsubst %.cpp, $(COMPILE_DIR)/%.o, $(CPP_SRCS))
CPP_DEP = $(patsubst %.cpp, $(COMPILE_DIR)/%.cpp.d, $(CPP_SRCS))OBJS = $(CPP_OBJS) $(C_OBJS)
DEP_ALL = $(CPP_DEP) $(C_DEP)$(shell if [ ! -d $(COMPILE_DIR) ]; then mkdir $(COMPILE_DIR); fi)
$(shell if [ ! -d $(BIN_DIR) ]; then mkdir $(BIN_DIR); fi)BIN =
ifeq ($(target), ) #如果是空的
BIN = httpServer
else
BIN := $(target)
endifTARGET=$(BIN_DIR)/$(BIN)all: $(TARGET)-include $(DEP_ALL)$(TARGET): $(OBJS) $(COMPILE_DIR)/mongoose.o$(CPP) $(CFLAGS) $^ -o $@ $(COMPILE_DIR)/%.o: %.cpp $(COMPILE_DIR)/%.cpp.d$(CPP) $(CFLAGS) -c $< -o $@$(COMPILE_DIR)/%.cpp.d: %.cpp$(CPP) $(CFLAGS) -MM -E -c $< -o $@@sed 's/.*\.o/$(subst /,\/,$(dir $@))&/g' $@ > $@.tmp@mv $@.tmp $@$(COMPILE_DIR)/mongoose.o: ../../mongoose.c$(CC) $(CFLAGS) -c $< -o $@$(COMPILE_DIR)/%.c.d: %.c$(CC) $(CFLAGS) -MM -E -c $< -o $@@sed 's/.*\.o/$(subst /,\/,$(dir $@))&/g' $@ > $@.tmp@mv $@.tmp $@.PHONY: clean
clean:rm -rf $(COMPILE_DIR) $(BIN_DIR)

同时把main.cpp里的书写格式也改了,还是习惯一行行的看代码:

// Copyright (c) 2020 Cesanta Software Limited
// All rights reserved#include <signal.h>
#include "mongoose.h"static int s_debug_level = MG_LL_INFO;
static const char *s_root_dir = ".";
static const char *s_listening_address = "http://0.0.0.0:8190";
static const char *s_enable_hexdump = "no";
static const char *s_ssi_pattern = "#.html";// Handle interrupts, like Ctrl-C
static int s_signo;
static void signal_handler(int signo) 
{s_signo = signo;
}// Event handler for the listening connection.
// Simply serve static files from `s_root_dir`
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) 
{if (ev == MG_EV_HTTP_MSG) {struct mg_http_message *hm = (mg_http_message *)ev_data, tmp = {0};struct mg_str unknown = mg_str_n("?", 1), *cl;struct mg_http_serve_opts opts = {0};//不能用ptr直接打印,需要根据lenMG_INFO(("method(%d): %s, uri(%d): %s, query(%d): %s, proto(%d): %s", hm->method.len, hm->method.ptr, hm->uri.len, hm->uri.ptr, hm->query.len, hm->query.ptr, hm->proto.len, hm->proto.ptr));MG_INFO(("method ptr: %p, uri ptr: %p, query ptr: %p, proto ptr: %p\n", hm->method.ptr, hm->uri.ptr, hm->query.ptr, hm->proto.ptr));//设置目录起点opts.root_dir = s_root_dir;opts.ssi_pattern = s_ssi_pattern;mg_http_serve_dir(c, hm, &opts);mg_http_parse((char *) c->send.buf, c->send.len, &tmp);cl = mg_http_get_header(&tmp, "Content-Length");if (cl == NULL) {cl = &unknown;}MG_INFO(("%.*s %.*s %.*s %.*s", (int) hm->method.len, hm->method.ptr,(int) hm->uri.len, hm->uri.ptr, (int) tmp.uri.len, tmp.uri.ptr,(int) cl->len, cl->ptr));}(void) fn_data;
}static void usage(const char *prog) 
{fprintf(stderr,"Mongoose v.%s\n""Usage: %s OPTIONS\n""  -H yes|no - enable traffic hexdump, default: '%s'\n""  -S PAT    - SSI filename pattern, default: '%s'\n""  -d DIR    - directory to serve, default: '%s'\n""  -l ADDR   - listening address, default: '%s'\n""  -v LEVEL  - debug level, from 0 to 4, default: %d\n",MG_VERSION, prog, s_enable_hexdump, s_ssi_pattern, s_root_dir,s_listening_address, s_debug_level);exit(EXIT_FAILURE);
}int main(int argc, char *argv[]) 
{char path[MG_PATH_MAX] = ".";struct mg_mgr mgr;struct mg_connection *c;int i;// Parse command-line flagsfor (i = 1; i < argc; i++) {if (strcmp(argv[i], "-d") == 0) {s_root_dir = argv[++i];} else if (strcmp(argv[i], "-H") == 0) {s_enable_hexdump = argv[++i];} else if (strcmp(argv[i], "-S") == 0) {s_ssi_pattern = argv[++i];} else if (strcmp(argv[i], "-l") == 0) {s_listening_address = argv[++i];} else if (strcmp(argv[i], "-v") == 0) {s_debug_level = atoi(argv[++i]);} else {usage(argv[0]);}}// Root directory must not contain double dots. Make it absolute// Do the conversion only if the root dir spec does not contain overridesif (strchr(s_root_dir, ',') == NULL) {realpath(s_root_dir, path);s_root_dir = path;}// Initialise stuffsignal(SIGINT, signal_handler);signal(SIGTERM, signal_handler);mg_log_set(s_debug_level);mg_mgr_init(&mgr);if ((c = mg_http_listen(&mgr, s_listening_address, cb, &mgr)) == NULL) {MG_ERROR(("Cannot listen on %s. Use http://ADDR:PORT or :PORT", s_listening_address));exit(EXIT_FAILURE);}if (mg_casecmp(s_enable_hexdump, "yes") == 0) {c->is_hexdumping = 1;}// Start infinite event loopMG_INFO(("Mongoose version : v%s", MG_VERSION));MG_INFO(("Listening on     : %s", s_listening_address));MG_INFO(("Web root         : [%s]", s_root_dir));while (s_signo == 0) {mg_mgr_poll(&mgr, 1000);}mg_mgr_free(&mgr);MG_INFO(("Exiting on signal %d", s_signo));return 0;
}

在实际使用的时候需要注意 struct mg_str 结构体,如 mg_http_message 中的 method, uri, query, proto 等,代码里我只是好奇地想打印一下这些数据,然而结果并不是我想要的,如:

        MG_INFO(("method(%d): %s, uri(%d): %s, query(%d): %s, proto(%d): %s", hm->method.len, hm->method.ptr, hm->uri.len, hm->uri.ptr, hm->query.len, hm->query.ptr, hm->proto.len, hm->proto.ptr));MG_INFO(("method ptr: %p, uri ptr: %p, query ptr: %p, proto ptr: %p\n", hm->method.ptr, hm->uri.ptr, hm->query.ptr, hm->proto.ptr));

打印 mg_str 的时候使用了其 ptr 指针,而打印出这些指针可以看到它们指向的是连续的一个地址:

[2023/08/10 14:52:21 510890 Info] main.cpp:32:cb   method ptr: 0x1f30580, uri ptr: 0x1f30584, query ptr: 0x0, proto ptr: 0x1f30586

HTTP message format

0x1f30580 + 3(method 的长度) + 1(一个空格) = 0x1f30584,0x1f30584 + 1(uri的长度)+1(一个空格) = 0x1f30586。

使用了 std::string 

        std::string method(hm->method.ptr, hm->method.len);std::string uri(hm->uri.ptr, hm->uri.len);std::string proto(hm->proto.ptr, hm->proto.len);MG_INFO(("method: %s, uri: %s, proto: %s\n", method.c_str(), uri.c_str(), proto.c_str()));

 

相关文章:

Mongoose http server 例子

今天抽了点时间看了一下 mongoose的源码&#xff0c; github 地址&#xff0c;发现跟以前公司内部使用的不太一样&#xff0c;这里正好利用其 http server 例子来看一下。以前的 http message 结构体是这样的&#xff1a; /* HTTP message */ struct http_message {struct mg_…...

1、初识HTML

1、初识HTML 前端就是写一些基本的页面&#xff0c;HTML即超文本标记语言&#xff1a;Hyper Text Markup Language&#xff0c;超文本包括&#xff0c;文字、图片、音频、视频、动画等&#xff0c;HTML5&#xff0c;提供了一些新的元素和一些有趣的新特性&#xff0c;同时也建…...

线性代数(三) 线性方程组

前言 如何利用行列式&#xff0c;矩阵求解线性方程组。 线性方程组的相关概念 用矩阵方程表示 齐次线性方程组&#xff1a;Ax0&#xff1b;非齐次线性方程组&#xff1a;Axb. 可以理解 齐次线性方程组 是特殊的 非齐次线性方程组 如何判断线性方程组的解 其中R(A)表示矩阵A的…...

Apoll 多项式规划求解

一、纵向规划 void QuarticPolynomialCurve1d::ComputeCoefficients(const float x0, const float dx0, const float ddx0, const float dx1,const float ddx1, const float p) {if (p < 0.0) {std::cout << "p should be greater than 0 at line 140." &…...

ssm亚盛汽车配件销售业绩管理统源码和论文PPT

ssm亚盛汽车配件销售业绩管理统源码和论文PPT007 开发工具&#xff1a;idea 数据库mysql5.7(mysql5.7最佳) 数据库链接工具&#xff1a;navcat,小海豚等 开发技术&#xff1a;java ssm tomcat8.5 研究的意义 汽车配件销售类企业近年来得到长足发展,在市场份额不断扩大同时…...

发布属于自己的 npm 包

1 创建文件夹&#xff0c;并创建 index.js 在文件中声明函数&#xff0c;使用module.exports 导出 2 npm 初始化工具包&#xff0c;package.json 填写包的信息&#xff08;包的名字是唯一的&#xff09; npm init 可在这里写包的名字&#xff0c;或者一路按回车&#xff0c;后…...

Redis主从复制和哨兵架构图,集成Spring Boot项目实战分享

目录 1. Redis 主从复制2. Redis 哨兵架构3. 集成spring boot项目案列 Redis 主从复制和哨兵架构是 Redis 集群的重要组成部分&#xff0c;用于提高 Redis 集群的可用性和性能。以下是 Redis 主从复制和哨兵架构的详细介绍&#xff0c;包括架构图和 Java 代码详解。 1. Redis …...

java中try-with-resources自动关闭io流

文章目录 java中try-with-resources自动关闭io流0 简要说明try-with-resources java中try-with-resources自动关闭io流 0 简要说明 在传统的输入输出流处理中&#xff0c;我们一般使用的结构如下所示&#xff0c;使用try - catch - finally结构捕获相关异常&#xff0c;最后不…...

Games101学习笔记 -光栅化

光栅化 经过MVP矩阵和视口变换后&#xff0c;我们就可以从相机的角度看到一个和屏幕大小一致的二维平面。 那么把这个看到的二维平面应用到我们的屏幕上的过程就是光栅化。在这儿我们需要补充一个概念-像素&#xff1a; 像素&#xff1a; 一个二位数组&#xff0c;数组中每个…...

Pytorch量化之Post Train Static Quantization(训练后静态量化)

使用Pytorch训练出的模型权重为fp32&#xff0c;部署时&#xff0c;为了加快速度&#xff0c;一般会将模型量化至int8。与fp32相比&#xff0c;int8模型的大小为原来的1/4, 速度为2~4倍。 Pytorch支持三种量化方式&#xff1a; 动态量化&#xff08;Dynamic Quantization&…...

Sql奇技淫巧之EXIST实现分层过滤

在这样一个场景&#xff0c;我 left join 了很多张表&#xff0c;用这些表的不同列来过滤&#xff0c;看起来非常合理 但是出现的问题是 left join 其中一张或多张表出现了笛卡尔积&#xff0c;且无法消除 FUNCTION fun_get_xxx_helper(v_param_1 VARCHAR2,v_param_2 VARCHAR2…...

Linux下升级jdk1.8小版本

先输入java -version 查看是否安装了jdk java -version &#xff08;1&#xff09;如果没有返回值&#xff0c;直接安装新的jdk即可。 &#xff08;2&#xff09;如果有返回值&#xff0c;例如&#xff1a; java version "1.8.0_251" Java(TM) SE Runtime Enviro…...

【Mysql】数据库基础与基本操作

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…...

87 | Python人工智能篇 —— 机器学习算法 决策树

本教程将深入探讨决策树的基本原理,包括特征选择方法、树的构建过程以及剪枝技术,旨在帮助读者全面理解决策树算法的工作机制。同时,我们将使用 Python 和 scikit-learn 库演示如何轻松地实现和应用决策树,以及如何对结果进行可视化。无论您是初学者还是有一定机器学习经验…...

【计算机视觉】干货分享:Segmentation model PyTorch(快速搭建图像分割网络)

一、前言 如何快速搭建图像分割网络&#xff1f; 要手写把backbone &#xff0c;手写decoder 吗&#xff1f; 介绍一个分割神器&#xff0c;分分钟搭建一个分割网络。 仓库的地址&#xff1a; https://github.com/qubvel/segmentation_models.pytorch该库的主要特点是&#…...

解析湖仓一体的支撑技术及实践路径

自2021年“湖仓一体”首次写入Gartner数据管理领域成熟度模型报告以来&#xff0c;随着企业数字化转型的不断深入&#xff0c;“湖仓一体”作为新型的技术受到了前所未有的关注&#xff0c;越来越多的企业视“湖仓一体” 为数字化转型的重要基础设施。 01 数据平台的发展历程…...

40.利用欧拉法求解微分方程组(matlab程序)

1.简述 求解微分方程的时候&#xff0c;如果不能将求出结果的表达式&#xff0c;则可以对利用数值积分对微分方程求解&#xff0c;获取数值解。欧拉方法是最简单的一种数值解法。前面介绍过MATLAB实例讲解欧拉法求解微分方程&#xff0c;今天实例讲解欧拉法求解一阶微分方程组。…...

OpenAI-Translator 实战总结

最近在极客时间学习《AI 大模型应用开发实战营》&#xff0c;自己一边跟着学一边开发了一个进阶版本的 OpenAI-Translator&#xff0c;在这里简单记录下开发过程和心得体会&#xff0c;供有兴趣的同学参考 功能概览 通过openai的chat API&#xff0c;实现一个pdf翻译器实现一个…...

【工业机器人】用于轨迹规划和执行器分析的机械手和移动机器人模型(MatlabSimulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

开源在线文档服务OnlyOffice

开源在线文档服务OnlyOffice应用启动与示例运行 - 掘金 ONLYOFFICE API 文档 - Example - IDEA运行Java示例 | ONLYOFFICE中文网 NEXTCLOUDonlyoffice的搭建和使用_nextcloud onlyoffice_莫冲的博客-CSDN博客 OnlyOffice java 部署使用&#xff0c;文件流方式 预览文件 | 言曌博…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...