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()));

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css的transform样式计算-第一节

本文作者为 360 奇舞团前端开发工程师 引言 在使用 css 样式进行样式的缩放、旋转等设置时&#xff0c;思考了一下它的较浅层的原理&#xff0c;恩&#xff0c;这个阶段都 是一些初高的数学计算&#xff0c;从新看这里的时候顺便捡了捡初高中的数学&#xff0c;比如三角函数之类…

CSS:盒子模型 与 多种横向布局方法

目录 盒子模型块级盒子内联级盒子内联块级盒子弹性盒子display 改变模型区域划分text 内容区padding 填充区border 边框区margin 外边距直接设置盒子大小 布局横向布局方法一 float 浮起来方法二 内联块级元素实现方法三 弹性盒子模型 盒子模型 块级盒子 独占一行&#xff0c…

React中使用mobx管理状态数据使用样例

MobX 是一个身经百战的库&#xff0c;它通过运用透明的函数式响应编程&#xff08;Transparent Functional Reactive Programming&#xff0c;TFRP&#xff09;使状态管理变得简单和可扩展。官网地址&#xff1a;关于 MobX | MobX中文文档 | MobX中文网 安装依赖 mobx-react-…

QT的信号槽的四种写法和五种链接方式

目录 四种信号槽写法&#xff1a; 五种连接方式&#xff1a; 实例&#xff1a; 常见错误及改正&#xff1a; 错误1: 未连接信号与槽 错误2: 信号和槽参数不匹配 错误3: 未使用Q_OBJECT宏 错误4: 跨线程连接未处理 在Qt中&#xff0c;信号&#xff08;Signal&#xff09…

openEuler-OECA考试报名火热开启,尊享半价优惠 作者:HopeInfra 发布时间:2023-08-10

近日&#xff0c;润和软件人才评定报名系统已成功上线运行&#xff0c;现openEuler-OECA人才评定考试报名优惠活动火热开启&#xff0c;欢迎大家报名咨询&#xff01; 关于openEuler人才评定 随着openEuler及其发行版本在各个行业使用量逐年增多&#xff0c;相关人才的评定诉求…

突破笔试:力扣129. 求根节点到叶节点数字之和

1. 题目链接&#xff1a;129. 求根节点到叶节点数字之和 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。每条从根节点到叶节点的路径都代表一个数字&#xff1a;例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 …

http相关知识点

文章目录 长链接http周边会话保持方案1方案2 基本工具postmanFiddlerFiddler的原理 长链接 一张网页实际上可能会有多种元素组成&#xff0c;这也就说明了网页需要多次的http请求。可由于http是基于TCP的&#xff0c;而TCP创建链接是有代价的&#xff0c;因此频繁的创建链接会…

大数据Flink(五十六):Standalone伪分布环境(开发测试)

文章目录 Standalone伪分布环境(开发测试) 一、架构图 二、环境准备 三、下载安装包</

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马&#xff08;最后是我遇到的问题&#xff09; cover-view是气泡弹窗&#xff0c;可以自定义弹窗&#xff0c;要配合js&#xff1a;customCallout&#xff0c;如果是非自定义的话&#xff1a;callout&#xff08;可以修改颜色、边框宽度、圆角…

java输出GB2312、GBK、GB18030、UTF-8所有的字符

相关文章 【转】彻底搞明白 GB2312、GBK 、GB18030和UTF-8 1.ASICII、GB2312、GBK、GB18030 以及 UTF8 的关系 2.编写代码 引入依赖&#xff1a;hutool工具类 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId>&…

轻松批量自定义重命名,为文件夹加上个性化编号!

在日常生活和工作中&#xff0c;我们经常需要对大量的文件夹进行重命名&#xff0c;以更好地管理和整理文件。然而&#xff0c;手动逐个修改文件夹名称费时费力&#xff0c;效率低下。现在&#xff0c;我们为您推荐一款简单易用的工具&#xff0c;可以帮助您快速批量自定义重命…

LoRaWAN网关与网络服务器(NS)的通信CUPS 协议介绍

LoRa Basics™ Station 定期查询 CUPS 服务器以获取更新。该协议是 HTTP/REST,使用Credentials中描述的客户端/服务器身份验证方法。对于每个查询,工作站都会提供有关其当前状态的信息,并接收包含其 LNS 和 CUPS 凭证更新的二进制 blob,以及具有任意更新的通用数据段。 通…

网络安全的相关知识点

网络安全威胁类型&#xff1a; 1.窃听&#xff1a;广播式网络系统。 2.假冒 3.重放&#xff1a;重复一份报文或者报文的一部分&#xff0c;以便产生一个被授权的效果。 4.流量分析 5.数据完整性破坏 6.拒绝服务 7.资源的非授权使用 8.陷门和特洛伊木马&#xff1a;木马病毒有客…

Java课题笔记~ Spring 的事务管理

一、Spring 的事务管理 事务原本是数据库中的概念&#xff0c;在 Dao 层。但一般情况下&#xff0c;需要将事务提升到业务层&#xff0c;即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。 在 Spring 中通常可以通过以下两种方式来实现对事务的管理&#xff…

花样滑冰选手骨骼点动作识别

2023 CCF BDCI 基于飞桨实现花样滑冰选手骨骼点动作识别 16名方案以及总结 比赛任务 花样滑冰与其他运动项目相比&#xff0c;其动作类型的区分难度更大&#xff0c;这对识别任务来说是极大的挑战。对于花样滑冰动作识别任务&#xff0c;主要难点如下&#xff1a; (1) 花样滑…

Python-OpenCV中的图像处理-图像梯度

Python-OpenCV中的图像处理-图像梯度 图像梯度Sobel 算子和 Scharr 算子Laplacian 算子 图像梯度 图像梯度&#xff0c;图像边界等使用到的函数有&#xff1a; cv2.Sobel()&#xff0c; cv2.Scharr()&#xff0c; cv2.Laplacian() 等原理&#xff1a;梯度简单来说就是求导。Op…

fastadmin、vue、react图标库适用于多种框架

在二开fastadmin中&#xff0c;在写vue以及react时&#xff0c;侧边导航栏以及按钮中常常需要很多图标&#xff0c;那么这些图标应该去哪里得到呢&#xff0c;在这里给大家一个链接&#xff0c;这里有丰富的图标库&#xff0c;可以找到自己想要的进行使用。 点击下方链接&…

github pages 用法详解 发布自己的网站

github pages 基础用法 URL 规则 假设你的 github 帐号为 mygithub&#xff0c;需要发布的仓库名为 myrepo&#xff0c;那么 pages 的 URL 为&#xff1a; https://mygithub.github.io/myrepo 添加内容 用任意编辑器写好&#xff08;或者生成&#xff09;标准的网页内容&a…

苹果正在测试新款Mac mini:搭载M3芯片 配备24GB大内存

据悉苹果目前正在测试新的Mac机型&#xff0c;亮点是采用最新的M3芯片。 据报道&#xff0c;首款搭载M3芯片的设备应该是13英寸的MacBook Pro和重新设计的MacBook Air&#xff0c;Mac mini机型并不在名单上。 M3和M2同样拥有最多8个核心&#xff0c;分别为4个性能核和4个能效核…

OpenAI-Translator 实战总结

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