# API-libmongoose — 嵌入式 HTTP/WebSocket 网络库 > 版本: v1.0 > 日期: 2026-07-08 > 来源: Mongoose v7.22 (MIT 许可,https://github.com/cesanta/mongoose) > 状态: ✅ 导入完成,x86 + ARM 双平台编译通过(零警告) --- ## 1. 模块概述 libmongoose 是 Mongoose v7.22 开源库的封装模块。Mongoose 是一个**单文件、纯 C 实现的嵌入式网络库**,广泛用于 IoT 和嵌入式设备。本模块主要用于 RTU 的 Web 管理服务(`libweb_server`),提供 HTTP REST API 和 WebSocket 双向通信能力。 | 功能 | 说明 | |------|------| | HTTP 服务器 | 解析请求、路由匹配、JSON 响应,用于 REST API | | WebSocket | 双向消息推送(实时遥测数据、告警通知) | | 事件驱动 | 基于 epoll 的异步 IO,单线程管理所有连接 | | 定时器 | 毫秒级软定时器,无需额外线程 | | 跨平台 | Linux / FreeRTOS / Zephyr / ESP32 等,本工程只用 Linux | ### 架构位置 ``` libweb_server (system/) — REST API + WebSocket 管理 │ ▼ libmongoose (protocol/) — HTTP/WS 协议栈 │ ▼ Linux kernel socket + epoll ``` --- ## 2. 文件结构 ``` src/protocol/libmongoose/ ├── inc/ │ ├── myMongoose.h # RTU 适配头(编译配置宏 + #include "mongoose.h") │ └── mongoose.h # Mongoose v7.22 头文件(5748 行,上游文件) └── src/ └── mongoose.c # Mongoose v7.22 实现(31786 行,上游文件) release/ ├── inc/ │ ├── myMongoose.h # 拷贝自 src,供其他模块包含 │ └── mongoose.h # 拷贝自 src └── x86/lib/ └── libmongoose.a # x86 编译产物(462KB) └── arm/lib/ └── libmongoose.a # ARM 编译产物(471KB) ``` --- ## 3. 编译配置 在 `myMongoose.h` 中定义以下宏(必须在 `#include "mongoose.h"` 之前): | 宏 | 值 | 说明 | |------|-----|------| | `MG_ENABLE_LOG` | 1 | 启用内置日志(printf 到 stderr) | | `MG_ENABLE_FILE` | 0 | 禁用文件系统(RTU 不通过 mongoose 提供静态文件) | | `MG_ENABLE_POSIX_FS` | 0 | 禁用 POSIX 文件 API | | `MG_ENABLE_EPOLL` | 1 | 启用 epoll(Linux 高效 IO 多路复用) | | `MG_ENABLE_POLL` | 1 | 启用 poll(epoll 回退方案) | | `MG_ENABLE_SOCKET` | 1 | 使用 Linux 内核 socket | --- ## 4. 核心数据结构 ### 4.1 mg_mgr — 事件管理器 ```c struct mg_mgr { struct mg_connection *conns; /* 活动连接链表 */ struct mg_timer *timers; /* 定时器链表 */ // ... 内部字段 }; ``` 每个进程只需一个 `mg_mgr` 实例,管理所有连接和定时器。 ### 4.2 mg_connection — 连接 ```c struct mg_connection { struct mg_connection *next; /* 链表指针 */ struct mg_mgr *mgr; /* 所属管理器 */ struct mg_addr peer; /* 对端地址 */ void *fd; /* socket 文件描述符 */ unsigned long id; /* 连接 ID */ unsigned is_websocket : 1; /* 是否为 WebSocket 连接 */ unsigned is_client : 1; /* 是否为客户端连接 */ // ... }; ``` ### 4.3 事件类型 ```c enum { MG_EV_ERROR, /* 错误 */ MG_EV_OPEN, /* 连接建立(仅客户端出站连接) */ MG_EV_POLL, /* mg_mgr_poll() 每次迭代触发 */ MG_EV_RESOLVE, /* DNS 解析完成 */ MG_EV_CONNECT, /* TCP 连接完成 */ MG_EV_ACCEPT, /* TCP 新连接接受 */ MG_EV_TLS_HS, /* TLS 握手完成 */ MG_EV_READ, /* 数据可读 */ MG_EV_WRITE, /* 数据可写 */ MG_EV_CLOSE, /* 连接关闭 */ MG_EV_HTTP_MSG, /* HTTP 请求/响应解析完成 */ MG_EV_HTTP_CHUNK, /* HTTP 分块数据 */ MG_EV_WS_OPEN, /* WebSocket 握手完成 */ MG_EV_WS_MSG, /* WebSocket 消息到达 */ MG_EV_WS_CTL, /* WebSocket 控制帧 */ MG_EV_MQTT_CMD, /* MQTT 命令 */ MG_EV_MQTT_MSG, /* MQTT 消息 */ MG_EV_MQTT_OPEN, /* MQTT 连接建立 */ MG_EV_SNTP_TIME, /* SNTP 时间 */ MG_EV_USER, /* 用户自定义事件起点 */ }; ``` --- ## 5. 接口函数 ### 5.1 生命周期 ```c /** 初始化事件管理器 */ void mg_mgr_init(struct mg_mgr *mgr); /** 事件循环(每次调用处理一批事件,阻塞不超过 ms 毫秒) */ void mg_mgr_poll(struct mg_mgr *mgr, int ms); /** 销毁事件管理器(关闭所有连接,释放所有内存) */ void mg_mgr_free(struct mg_mgr *mgr); ``` **典型用法**: ```c struct mg_mgr mgr; mg_mgr_init(&mgr); /* 注册 HTTP/WS 监听 + 定时器 */ // ... while (running) { mg_mgr_poll(&mgr, 50); /* 50ms 超时 */ } mg_mgr_free(&mgr); ``` ### 5.2 HTTP 服务器 ```c /** 创建 HTTP 监听连接 */ struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data); /** 获取 HTTP 请求/响应消息 */ int mg_http_get_request_len(const unsigned char *buf, size_t buf_len); struct mg_http_message *mg_http_parse(const char *buf, size_t len); struct mg_http_message *mg_http_parse2(const char *buf, size_t len); /** 响应辅助 */ void mg_http_reply(struct mg_connection *c, int status_code, const char *headers, const char *body_fmt, ...); void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, const char *root); /** 路由匹配 */ bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps); bool mg_http_match_uri(const struct mg_http_message *hm, const char *pattern); ``` **REST API 示例**: ```c static void fn(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_http_match_uri(hm, "/api/status")) { mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"status\":\"ok\"}"); } } } mg_http_listen(&mgr, "http://0.0.0.0:8080", fn, NULL); ``` ### 5.3 WebSocket ```c /** 升级 HTTP 连接到 WebSocket */ void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *hm, const char *fmt, ...); /** 发送 WebSocket 消息 */ size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op); /** 格式化发送 WebSocket 消息 */ size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...); /** 封装非 WS socket 为 WS 帧(用于代理) */ size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op, const void *buf, size_t buf_len); /** 主动连接 WebSocket 服务器(客户端模式) */ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data, const char *fmt, ...); ``` **WebSocket 帧操作码 (op)**: ```c #define WEBSOCKET_OP_CONTINUE 0 /* 继续帧 */ #define WEBSOCKET_OP_TEXT 1 /* 文本消息 */ #define WEBSOCKET_OP_BINARY 2 /* 二进制消息 */ #define WEBSOCKET_OP_CLOSE 8 /* 关闭握手 */ #define WEBSOCKET_OP_PING 9 /* Ping */ #define WEBSOCKET_OP_PONG 10 /* Pong */ ``` **WebSocket 服务端示例**: ```c static void fn(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("/ws"), NULL)) { mg_ws_upgrade(c, hm, NULL); } } else if (ev == MG_EV_WS_MSG) { struct mg_ws_message *wm = (struct mg_ws_message *)ev_data; /* 回显消息 */ mg_ws_send(c, wm->data.buf, wm->data.len, WEBSOCKET_OP_TEXT); } } ``` ### 5.4 定时器 ```c /** 添加一次性定时器 */ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds, unsigned flags, void (*fn)(void *), void *arg); /** 定时器标志 */ #define MG_TIMER_REPEAT 1 /* 周期性定时器 */ #define MG_TIMER_RUN_NOW 2 /* 立即运行一次 */ ``` ### 5.5 通用收发 ```c /** 发送原始数据 */ bool mg_send(struct mg_connection *c, const void *buf, size_t len); /** 格式化发送 */ size_t mg_printf(struct mg_connection *c, const char *fmt, ...); size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap); /** 关闭连接 */ void mg_close_conn(struct mg_connection *c); ``` --- ## 6. 使用约束与注意事项 ### 6.1 线程安全 - `mg_mgr_poll()` 必须在**单线程**中调用 - 如需要多线程,通过 `mg_wakeup()` 向事件循环投递消息 ### 6.2 内存管理 - 所有通过 `mg_http_listen()` 创建的连接在 `mg_mgr_free()` 时自动关闭释放 - `mg_http_message` 中的 `hm->body`、`hm->query` 等字段为协议栈内部缓冲区,**不可手动 free** ### 6.3 与 RTU 的集成方式 - `libweb_server` 作为 RTU 的独立线程模块,在线程内创建自己的 `mg_mgr` - 通过 X-Macro 框架的定时器触发 `mg_mgr_poll()` - HTTP 路由中使用 `dc_get_signal_val()` 获取实时数据,`dc_set_out_signal_val()` 发布前端写入的数据 ### 6.4 日志说明 mongoose 内部使用 `printf` 向 stderr 输出日志(`MG_ENABLE_LOG=1`)。在 RTU 装置上 stderr 通常重定向到 `/dev/null` 或 syslog。如需捕获 mongoose 日志,可定义 `MG_ENABLE_CUSTOM_LOG=1` 并提供自定义 `MG_LOG()` 宏。 --- ## 7. 依赖关系 ### 7.1 本模块依赖 - **无**(mongoose 是纯 C、零依赖的单文件库,直接使用 Linux socket API) ### 7.2 依赖本模块的模块 | 模块 | 用途 | |------|------| | `libweb_server` (system/) | HTTP REST API + WebSocket 通信 | ### 7.3 模块依赖图 ``` ┌──────────────────┐ │ libweb_server │ (RTU 线程模块) │ REST API + WS │ └────────┬─────────┘ │ myMongoose.h ▼ ┌──────────────────┐ │ libmongoose │ (纯 C 协议栈) │ HTTP + WebSocket │ └────────┬─────────┘ │ ▼ Linux Socket API + epoll ``` --- ## 8. 编译与构建 ```bash # 编译 libmongoose.a cd release/src/protocol/libmongoose make -f makefile all # x86 make -f makefile CROSS=arm all # ARM # 参与全量构建 cd release && ./build.sh # x86 cd release && ./build.sh arm # ARM ``` --- ## 9. 许可证 Mongoose 使用 **MIT 许可证**(商业友好)。完整许可文本见 `mongoose.h` 头部注释。 --- ## 10. 参考链接 - [Mongoose 官方文档](https://mongoose.ws/documentation/) - [Mongoose GitHub](https://github.com/cesanta/mongoose) - [WebSocket RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455) - [HTTP/1.1 RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230)