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.hqwc.cn/news/65754.html

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

相关文章

用Python编写的小游戏:探索游戏世界的乐趣

探索开始 引言&#xff1a;第一部分&#xff1a;猜数字游戏代码案例1&#xff1a; 第二部分&#xff1a;石头剪刀布游戏代码案例2&#xff1a; 第三部分&#xff1a;迷宫游戏代码案例3&#xff1a; 总结&#xff1a; 引言&#xff1a; Python是一种简单易学的编程语言&#xf…

CSS:服务器字体 与 响应式布局(用法 + 例子 + 效果)

文章目录 服务器字体定义 服务器字体使用例子 响应式布局设备类型设备特性例子 服务器字体 解决字体不一致而产生的。 首先&#xff0c;在网上把字体下载好。 定义 服务器字体 font-face{font-family:字体名称;src:url(字体资源路径); }使用 在需要使用的选择器里加上 font…

探索数据之美:初步学习 Python 柱状图绘制

文章目录 一 基础柱状图1.1 创建简单柱状图1.2 反转x和y轴1.3 数值标签在右侧1.4 演示结果 二 基础时间线柱状图2.1 创建时间线2.2 时间线主题设置取值表2.3 演示结果 三 GDP动态柱状图绘制3.1 需求分析3.2 数据文件内容3.3 列表排序方法3.4 参考代码3.5 运行结果 一 基础柱状图…

c++ 学习系列 -- 智能指针

一 为什么引入智能指针&#xff1f;解决了什么问题&#xff1f; C 程序设计中使用堆内存是非常频繁的操作&#xff0c;堆内存的申请和释放都由程序员自己管理。但使用普通指针&#xff0c;容易造成内存泄露&#xff08;忘记释放&#xff09;、二次释放、程序发生异常时内存泄…

Remote Sensing,2023 | 基于SBL的分布式毫米波相干雷达成像的高效实现

Remote Sensing,2023 | 基于SBL的分布式毫米波相干雷达成像的高效实现 注1&#xff1a;本文系“无线感知论文速递”系列之一&#xff0c;致力于简洁清晰完整地介绍、解读无线感知领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; MobiCom, Sigcom, MobiSys, NSDI…

【对于一维信号的匹配】对一个一维(时间)信号y使用自定义基B执行匹配追踪(MP)研究(Matlab代码实现)

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

Tesseract用OpenCV进行文本检测

我没有混日子&#xff0c;只是辛苦的时候没人看到罢了 一、什么是Tesseract Tesseract是一个开源的OCR&#xff08;Optical Character Recognition&#xff09;引擎&#xff0c;OCR是一种技术&#xff0c;它可以识别和解析图像中的文本内容&#xff0c;使计算机能够理解并处理…

【LeetCode】617.合并二叉树

题目 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重叠…

k8s常用资源管理 控制

目录 Pod&#xff08;容器组&#xff09;&#xff1a;Pod是Kubernetes中最小的部署单元&#xff0c;可以包含一个或多个容器。Pod提供了一种逻辑上的封装&#xff0c;使得容器可以一起共享网络和存储资源 1、创建一个pod 2、pod管理 pod操作 目录 创建Pod会很慢 Pod&…

Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的固定帧率(C++)

Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的固定帧率&#xff08;C&#xff09; Baumer工业相机Baumer工业相机的固定帧率功能的技术背景CameraExplorer如何查看相机固定帧率功能在BGAPI SDK里通过函数设置相机固定帧率 Baumer工业相机通过BGAPI SDK设置相机固定帧…

【图像去噪的滤波器】非局部均值滤波器的实现,用于鲁棒的图像去噪研究(Matlab代码实现)

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

【C语言】每日一题(错误的集合)

最近在牛客、力扣上做题&#xff0c;花费海量时间&#xff0c;苦不堪言&#xff0c;有时绞尽脑汁也想不出&#xff0c;痛定思痛&#xff0c;每日记录写的比较困难的题。 错误的集合 题目如上图所示 题主乍看之下觉得很简单&#xff0c;再看例子&#xff0c;不就是一个有序数组…