cesanta/mongoose
GitHub: cesanta/mongoose
Mongoose 是一个跨平台的嵌入式网络库,为 C/C++ 提供轻量级事件驱动 API,支持 HTTP、WebSocket、MQTT 等多种协议,可运行于裸机、RTOS 和主流操作系统之上。
Stars: 12627 | Forks: 2890
# Mongoose - 嵌入式 Web 服务器 / 嵌入式网络库
[](https://opensource.org/licenses/gpl-2.0.php)
[](https://github.com/cesanta/mongoose/actions)
[](https://codecov.io/gh/cesanta/mongoose)
[](https://issues.oss-fuzz.com/issues?sort=-opened&can=1&q=proj:mongoose)
Mongoose 是一个用于 C/C++ 的网络库。它为 TCP、UDP、HTTP、WebSocket、MQTT 和其他协议提供了事件驱动的非阻塞 API。它专为连接设备并将其上线而设计。自 2004 年上市以来,已被大量开源和商业产品使用——它甚至运行在国际空间站上!Mongoose 使嵌入式网络编程变得快速、健壮且简单。功能包括:
- 跨平台:
- 运行于 Linux/UNIX、MacOS、Windows、Android
- 运行于 ST、NXP、ESP32、Nordic、TI、Microchip、Infineon、Renesas 及其他芯片
- 一次编写代码 - 即可在任何地方运行
- 非常适合统一公司内部的网络基础设施代码
- 内置协议:plain TCP/UDP、SNTP、HTTP、MQTT、Websocket 等
- 异步 DNS 解析器
- 极小的静态和运行时占用
- 源代码同时符合 ISO C 和 ISO C++ 标准
- 易于集成:只需将 [mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) 和 [mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h) 文件复制到您的源码树中
- 内置 TCP/IP 协议栈,包含用于裸机或 RTOS 系统的驱动程序
- 可用驱动:STM32F, STM32H; NXP RT1xxx; TI TM4C; Microchip SAME54; Wiznet W5500
- 在裸机 ST Nucleo 开发板上完整的 Web 设备仪表盘仅需 6 个文件
- 相比之下,CubeIDE 生成的 HTTP 示例有 400 多个文件
- 可以运行在现有支持 BSD API 的 TCP/IP 协议栈之上,例如 lwIP、Zephyr、Azure 等
- 内置 TLS 1.3 ECC 协议栈。也可以使用外部 TLS 库 - mbedTLS、OpenSSL 或其他
- 实现网络功能不依赖任何其他软件
- 针对 STM32 H5、STM32 H7 的内置固件更新
完整文档、视频、案例研究等请参阅 https://mongoose.ws/。
## 支持的平台
Mongoose 可以在任何支持 BSD socket API 的 TCP/IP 协议栈之上运行。
第三方 TCP/IP 协议栈支持的平台:
| TCP/IP stack | Notes |
| :-------------- | :------- |
| **lwIP** | 所有运行 lwIP 的设备,例如 ESP32, ESP32S3, ESP32C3, ESP32C6 等 |
| **Zephyr** | Zephyr 支持的所有设备 |
| **Other** | 任何其他支持 BSD socket API 的 TCP/IP 协议栈,例如 Amazon FreeRTOS-TCP |
| **Linux, Mac, Windows** | 工作站、服务器、单板计算机、运行在 MPU 或 FPGA 上的嵌入式 Linux 设备 |
可选地,Mongoose 提供了自己内置的 TCP/IP 协议栈,无需额外软件即可实现网络功能。内置协议栈支持在裸机和 RTOS 环境中运行。
Mongoose 内置 TCP/IP 协议栈支持的平台:
| Hardware | Notes |
| :------------- | :------- |
| **STM32** | 所有内置以太网的 STM32 MCU:STM32Fxx, STM32H5xx, STM32H7xx |
| **NXP** | 所有内置以太网的 NXP MCU:IMXRT102x, IMXRT104x, IMXRT105x, IMXRT106x, IMXRT117x, RW612, MCXN94x |
| **Microchip** | 内置以太网的 ATSAME54 MCU |
| **Renesas** | 内置以太网的 RA5M, RA6M, RA8M MCU |
| **Infineon** | 内置以太网的 XMC4, XMC7 MCU |
| **Texas Instruments** | 内置以太网的 TM4C, TMS570 MCU |
| **Cypress WiFi** | 任何带有 CY43xx WiFi 芯片的 MCU,如 RP2040 Pico-W, RP2350 Pico2-W, Arduino Portenta |
| **Wiznet Ethernet** | 任何使用 Wiznet W5500 或 Wiznet 5100 MAC+PHY 芯片的 MCU |
| **Cellular** | NRF9160, SIM800 |
## 使用示例
以下简短的代码片段应该能让您了解 API 是多么简单,以及使用它创建应用程序是多么容易。
创建一个提供目录服务的简单 Web 服务器。HTTP 服务器的行为由其事件处理函数指定:
```
#include "mongoose.h" // To build, run: cc main.c mongoose.c
// HTTP server event handler function
void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts opts = { .root_dir = "./web_root/" };
mg_http_serve_dir(c, hm, &opts);
}
}
int main(void) {
struct mg_mgr mgr; // Declare event manager
mg_mgr_init(&mgr); // Initialise event manager
mg_http_listen(&mgr, "http://0.0.0.0:8000", ev_handler, NULL); // Setup listener
for (;;) { // Run an infinite event loop
mg_mgr_poll(&mgr, 1000);
}
return 0;
}
```
实现返回当前时间的 REST API 的 HTTP 服务器。JSON 格式:
```
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api/time/get"), NULL)) {
mg_http_reply(c, 200, "", "{%m:%lu}\n", MG_ESC("time"), time(NULL));
} else {
mg_http_reply(c, 500, "", "{%m:%m}\n", MG_ESC("error"), MG_ESC("Unsupported URI"));
}
}
}
```
订阅 `device1/rx` 主题并将收到的消息回显到 `device1/tx` 的 MQTT 客户端:
```
#include "mongoose.h"
static const char *s_mqtt_url = "mqtt://broker.hivemq.com:1883";
static struct mg_connection *s_mqtt_conn = NULL;
// MQTT connection event handler function
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_OPEN) {
MG_INFO(("%lu created, connecting to %s ...", c->id, s_mqtt_url));
} else if (ev == MG_EV_MQTT_OPEN) {
struct mg_mqtt_opts opts = {.qos = 1, .topic = mg_str("device1/rx")};
mg_mqtt_sub(c, &opts);
MG_INFO(("%lu connected, subscribing to %s", c->id, opts.topic.buf));
} else if (ev == MG_EV_MQTT_MSG) {
char response[100];
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
struct mg_mqtt_opts opts = {.qos = 1, .topic = mg_str("device1/tx")};
mg_snprintf(response, sizeof(response), "Received [%.*s] / [%.*s]",
mm->topic.len, mm->topic.buf, mm->data.len, mm->data.buf);
opts.message = mg_str(response);
mg_mqtt_pub(c, &opts);
} else if (ev == MG_EV_CLOSE) {
MG_INFO(("%u closing", c->id));
s_mqtt_conn = NULL;
}
}
// Reconnection timer function. If we get disconnected, reconnect again
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
if (s_mqtt_conn == NULL) {
struct mg_mqtt_opts opts = {.clean = true};
s_mqtt_conn = mg_mqtt_connect(mgr, s_mqtt_url, &opts, ev_handler, NULL);
}
}
int main() {
struct mg_mgr mgr; // Mongoose event manager. Holds all connections
mg_mgr_init(&mgr); // Initialise event manager
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr);
for (;;) {
mg_mgr_poll(&mgr, 1000); // Infinite event loop
}
return 0;
}
```
## 商业用途
- Mongoose 被数百家企业使用,从 Fortune 500 强巨头如 Siemens、Schneider Electric、Broadcom、Bosch、Google、Samsung、Qualcomm、Caterpillar 到小型企业
- 用于解决广泛的业务需求,例如在设备上实现 Web UI 界面、RESTful API 服务、遥测数据交换、产品远程控制、远程软件更新、远程监控等
- 已部署在全球数以亿计的生产环境设备中
- 请参阅来自我们尊贵客户的 [案例研究](https://mongoose.ws/case-studies/),如 [Schneider Electric](https://mongoose.ws/case-studies/schneider-electric/)(工业自动化)、[Broadcom](https://mongoose.ws/case-studies/broadcom/)(半导体)、[Pilz](https://mongoose.ws/case-studies/pilz/)(工业自动化)等
- 请参阅将 Mongoose 集成到其商业产品中的工程师的 [推荐语](https://mongoose.ws/testimonials/)
- 我们提供 [评估和商业许可](https://mongoose.ws/licensing/)、[支持](https://mongoose.ws/support/)、咨询和 [集成服务](https://mongoose.ws/integration/) - 请随时[联系我们](https://mongoose.ws/contact/)
## 安全性
我们要认真对待安全性:
1. Mongoose 仓库运行着由 [GitHub 驱动的持续集成测试](https://github.com/cesanta/mongoose/actions),该测试在每次提交到仓库时都会运行数百个单元测试。我们的 [单元测试](https://github.com/cesanta/mongoose/tree/master/test) 是使用现代地址消毒器技术构建的,有助于尽早发现安全漏洞
2. Mongoose 仓库已集成到 Google 的 [oss-fuzz 持续模糊测试器](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose) 中,该测试器会持续扫描潜在漏洞
3. 我们会收到来自独立安全组的定期漏洞报告,例如 [Cisco Talos](https://www.cisco.com/c/en/us/products/security/talos.html)、[Microsoft Security Response Center](https://www.microsoft.com/en-us/msrc)、[MITRE Corporation](https://www.mitre.org/)、[Compass Security](https://www.compass-security.com/en/) 等。如果发现漏洞,我们会按照行业最佳实践采取行动:暂缓发布,修复软件并通知所有拥有相应订阅的客户
4. 我们的某些客户(例如 NASA)有特定的安全要求并运行独立的安全审计,我们会收到通知,如果出现任何问题,我们会采取与 (3) 类似的行动。
## 如何报告安全漏洞
请发送电子邮件至 support@cesanta.com,并附上完整信息。
请勿创建 GitHub issue。
## 文章
嵌入式 Web 服务器、WebUI 集成和嵌入式网络技术的技术指南和深度解析:
- [嵌入式 Web 服务器:现代互联设备综合指南](https://mongoose.ws/articles/embedded-web-server-a-comprehensive-guide-for-modern-connected-devices/)
- [构建嵌入式 Web 设备仪表盘](https://mongoose.ws/articles/building-embedded-web-device-dashboard/)
- [ESP32 设备仪表盘:开发者分步指南](https://mongoose.ws/articles/esp32-device-dashboard/)
- [如何构建 STM32 Web 仪表盘](https://mongoose.ws/articles/stm32-device-dashboard/)
- [STM32 WebSocket 指南](https://mongoose.ws/articles/stm32-websocket-guide/)
- [STM32、ESP32 和嵌入式 Linux 上的 Web 文件管理器](https://mongoose.ws/articles/building-a-web-file-manager-on-stm32-esp32-embedded-linux/)
- [Zephyr RTOS 上的 Web 仪表盘](https://mongoose.ws/articles/web-dashboard-on-zephyr-rtos/)
- [在 STM32 上限制 TCP/IP RAM 使用](https://mongoose.ws/articles/limiting-tcpip-ram-usage-on-stm32/)
- [STM32 以太网详解](https://mongoose.ws/articles/stm32-ethernet-explained/)
- [微控制器上的 MQTT](https://mongoose.ws/articles/mqtt-on-a-microcontroller/)
- [STM32 OTA 固件更新](https://mongoose.ws/articles/stm32-ota-firmware-update/)
- [RP2350 OTA 固件更新](https://mongoose.ws/articles/rp2350-ota-firmware-update/)
- [STM32 以太网与缓存](https://mongoose.ws/articles/stm32-ethernet-and-cache/)
- [NXP RW612 OTA 固件更新](https://mongoose.ws/articles/rw612-ota-firmware-update/)
- [lwIP vs Mongoose - TCP/IP 协议栈集成基准测试](https://mongoose.ws/articles/lwip-vs-mongoose-tcpip-stack-integration/)
## 贡献
欢迎贡献!请遵循以下准则:
- 签署 [Cesanta CLA](https://cesanta.com/cla.html) 并发送 GitHub pull request
- 确保 PR 只有一个提交,并且只处理一个问题
标签:C/C++, ESP32, HTTP服务器, IoT设备联网, IP 地址批量处理, LangChain, NXP, RTOS, SNTP, ST, TCP, TCP/IP, TCP/IP协议栈, UDP, WebSocket, 事件驱动, 事务性I/O, 依赖分析, 单片机, 嵌入式Web服务器, 嵌入式开发, 嵌入式系统, 工业控制, 并发处理, 开源, 异步DNS, 智能家居, 物联网, 网络安全平台, 网络安全监控, 网络库, 网络编程, 航天软件, 裸机编程, 轻量级, 边缘计算, 非阻塞IO, 驱动开发