Mongoose --嵌入式 Web 服务器库笔记

avatar
作者
筋斗云
阅读量:0

一、Mongoose 的介绍

Mongoose 是一款嵌入式 Web 服务器库,具有跨平台、轻量级、支持多种网络协议、稳定可靠等特点。

be937a0c7f4df979fb686c9774924c4a.png

国内下载地址:

https://gitee.com/mirrors/mongoose.git

官方链接:

https://mongoose.ws/

参考说明文档:

https://mongoose.ws/documentation/

b32d28650caaa1a9bdd9ef4b2841dd1c.png

二、移植

Linux下移植非常简单,只需要将mongoose.c和mongoo.h文件复制到工程中即可。

aeda48b9b47a99ad9cfc8f9f2436c7d4.png

三、测试

根据手册进行简单测试,手册如下:

43eea800f383e676eb86df435c7ebeae.png

测试代码如下:‍

// 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:8000"; 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 = (struct mg_http_message *) ev_data;     if (mg_http_match_uri(hm, "/api/hello")) {              // On /api/hello requests,       mg_http_reply(c, 200, "", "{%m:%d}\n",                     MG_ESC("status"), 1);                   // Send dynamic JSON response     } else {                                                // For all other URIs,       struct mg_http_serve_opts opts = {.root_dir = "."};   // Serve files       mg_http_serve_dir(c, hm, &opts);                      // From root_dir     }   } }   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 flags   for (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 overrides   if (strchr(s_root_dir, ',') == NULL) {     realpath(s_root_dir, path);     s_root_dir = path;   }     // Initialise stuff   signal(SIGINT, signal_handler);   signal(SIGTERM, signal_handler);   mg_log_set(MG_LL_DEBUG);//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 loop   MG_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; }

在vs code中打开终端,输入如下指令

189c87da8999b729c1879b701e7e0741.png

可以看到程序自动运行。

打开浏览器输入ip地址和端口,可看到如下:

68646a02a936eb4eb029ec9cc8faa04b.png

输入测试指令,可获取到返回信息

http://192.168.1.195:8000/api/hello

4ba77642f77f3b1ef9887ea6311c903e.png

简单介绍下相关的函数和结构体,如下:

22a8c6196f447facdbdaed9c112f9bb7.png

71a4f8f3d95db95bc0caa0f87f6398fc.png

dea9b5ee0e9b9f3ed12c404074b8a814.png

简单示例,post和get方法:

static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data)  {   struct mg_http_message *hm = ev_data;   if (ev == MG_EV_HTTP_MSG)    {     if (strstr(hm->method.ptr, "POST"))     {       if (mg_http_match_uri(hm, "/haha"))       {           printf("这是POST请求\n");           printf("body:%s\n",hm->body);           mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{%.*s:%.*s}", (strlen("已经收到client请求")),"已经收到client请求", hm->message.len,hm->message);        }       else       {         mg_http_reply(c, 500, NULL, "{%.*s:%.*s}", (strlen("已经收到client请求")),"已经收到client请求",hm->message.len, hm->message);       }     }     else if (strstr(hm->method.ptr, "GET"))     {       if (mg_http_match_uri(hm, "/haha"))       {           printf("这是GET请求\n");           mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{%.*s:%.*s}", (strlen("已经收到client请求")),"已经收到client请求", hm->message.len,hm->message);       }       else       {         mg_http_reply(c, 500, NULL, "{%.*s:%.*s}", (strlen("已经收到client请求")),"已经收到client请求", hm->message.len,hm->message);       }     }     else     {         mg_http_reply(c, 500, NULL, "{%.*s:%.s}", (strlen("已经收到client请求")),"已经收到client请求",hm->message.len,hm->message);     }   }   (void) fn_data; }

欢迎关注公众号:嵌入式学习与实践

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!