小型的Web服务C开发库-mongoose
在现代嵌入式系统开发过程中可能需要在设备内部集成一个小型的 Web 服务器,以便实现远程监控、配置和管理等功能。mongoose 就是一个非常出色的基于事件驱动的嵌入式 Web 服务器,其遵循 GPLv2.0 许可协议。系极轻量、跨平台、事件驱动的嵌入式网络库;支持TCP、UDP、HTTP、WebSocket、MQTT,底层实现原理封装socket + IO多路复用(epoll/select)。Mongoose - Embedded Web Server / Embedded Network Library, Web UI builder for your device.
其主要优势在于其小巧灵活且功能强大。它的代码体积非常小,适合在资源受限的嵌入式环境中运行;同时提供了丰富的功能,能够满足各种嵌入式应用的需求。
该嵌入式 Web 服务器支持多种 HTTP 方法,如 GET、POST、PUT、DELETE 等,可以处理不同类型的请求。它还可以轻松地设置路由,将不同的 URL 路径映射到特定的处理函数上。
Mongoose is a network library for C/C++. It provides event-driven non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed for connecting devices and bringing them online. On the market since 2004, used by vast number of open source and commercial products - it even runs on the International Space Station! Mongoose makes embedded network programming fast, robust, and easy. Features include:
Cross-platform:
works on Linux/UNIX, MacOS, Windows, Android
works on STM32, NXP, ESP32, NRF52, TI, Microchip, and other
write code once - and it'll work everywhere
ideal for the unification of the network infrastructure code across company
Built-in protocols: plain TCP/UDP, SNTP, HTTP, MQTT, Websocket, and other
Asynchronous DNS resolver
Tiny static and run-time footprint
Source code is both ISO C and ISO C++ compliant
Easy to integrate: just copy mongoose.c and mongoose.h files to your source tree
Built-in TCP/IP stack with drivers for bare metal or RTOS systems
Available drivers: STM32F, STM32H; NXP RT1xxx; TI TM4C; Microchip SAME54; Wiznet W5500
A complete Web device dashboard on bare metal ST Nucleo boards is only 6 files
For comparison, a CubeIDE generated HTTP example is 400+ files
Can run on top of an existing TCP/IP stack with BSD API, e.g. lwIP, Zephyr, Azure, etc
Built-in TLS 1.3 ECC stack. Also can use external TLS libraries - mbedTLS, OpenSSL, or other
Does not depend on any other software to implement networking
Built-in firmware updates for STM32 H5, STM32 H7
1、事件管理器mg_mgr数据结构:
--整个网络模块的大脑;
--管理所有 socket、监听端口、客户端连接;
--全局唯一,一个程序只需要一个。
2、事件循环mg_mgr_poll()函数:
--大脑的无限循环;
--底层依靠操作系统 IO 多路复用(epoll/select);
--非阻塞、单线程、高并发;
--循环做 3 件事:等待网络事件(连接、收数据、发送完成、断开)、检测哪个 socket 有动作、分发事件调用自定义回调函数;
3、事件回调ev_handler()函数:
--业务逻辑的唯一入口;
--发生什么事,就进什么分支MG_EV_HTTP_MSG、MG_EV_READ、MG_EV_CLOSE等。
环境配置:将mongoose.h、mongoose.c拷贝至工程并添加。
以下是一段使用 mongoose 的代码示例:
#include <stdio.h>
#include "mongoose.h"
static void handle_request(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *)ev_data;
if (mg_vcmp(&hm->uri, "/hello") == 0) {
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello, World!");
} else {
mg_printf(c, "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot found");
}
}
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
struct mg_connection *c = mg_bind(&mgr, "8080", handle_request);
mg_set_protocol_http_websocket(c);
while (1) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
在这个示例中定义了一个请求处理函数 handle_request,当接收到对 /hello 路径的请求时,返回 “Hello, World!”,对于其他路径的请求则返回 “Not found”。在 main 函数中初始化了一个 mongoose 管理器,绑定到端口 8080,并设置了请求处理函数。然后进入一个循环,不断地处理请求。
它还支持静态文件服务、动态内容生成、SSL/TLS 加密等功能。它可以与各种嵌入式操作系统和硬件平台配合使用,为嵌入式设备提供便捷的网络服务。需要注意的是,由于遵循 GPLv2.0许可协议,使用 mongoose 的项目也必须遵循 GPL 协议进行开源发布,这对于一些商业项目可能会有一定的限制。其作为一个强大的嵌入式 Web 服务器,为嵌入式系统开发提供了便利。它的小巧灵活和丰富功能使其在嵌入式领域具有广泛的应用前景,开发者可以充分利用 mongoose 的优势,为嵌入式设备赋予强大的网络功能。
示例源码-main.c
#define MG_ENABLE_MQTT 0
#define MG_ENABLE_WEBSOCKET 0
#define MG_ENABLE_TLS 0
#define MG_ENABLE_DNS 0
#define MG_ENABLE_FILE 0
#define MG_ENABLE_SOCKET 1
#include <stdio.h>
#include "mongoose.h"
static void http_cb(struct mg_connection *c, int ev, void *d) {
if (ev == MG_EV_HTTP_MSG){
mg_http_reply(c, 200, "Content-Type:text/plain\r\n", "hello mongoose 7.x");
}
}
int main(void){
//定义一个 事件管理器
struct mg_mgr mgr;
/*
初始化事件管理器,管理所有网络连接、监听、事件
*/
mg_mgr_init(&mgr);
/*
在 0.0.0.0:8080 启动 HTTP 服务
任何浏览器访问 8080 端口
*/
mg_http_listen(&mgr, "http://0.0.0.0:8080", http_cb, NULL);
printf("http server run: 127.0.0.1:8080\n");
while (1){
/*
检查有没有新连接
检查有没有浏览器发来数据
检查连接是否断开
有事件 调用回调函数 http_cb
*/
mg_mgr_poll(&mgr, 10); //每隔10ms 轮询一次事件
}
mg_mgr_free(&mgr); //清理资源(目前不会调用到)
return 0;
}
最新版本:7.x
官方主页:
https://mongoose.ws/
https://github.com/cesanta/mongoose