STM32三方库 – 网络通信/Mongoose
C/C++网络库,提供事件驱动的非阻塞 TCP、UDP、HTTP、WebSocket、MQTT等协议的API。
跨平台:
-
适用于 Linux/UNIX、MacOS、Windows、Android;
-
适用于 STM32、NXP、ESP32、NRF52、TI、Microchip 等;
-
只需编写一次代码,即可在任何地方使用;
-
适用于跨公司统一网络基础设施代码;
内置协议:TCP/UDP、SNTP、HTTP、MQTT、Websocket等;
异步 DNS 解析器
极小的静态和运行时占用空间
源代码符合 ISO C 和 ISO C++ 标准
易于集成:只需将mongoose.c和mongoose.h文件复制到源代码树中即可
内置 TCP/IP 堆栈,带有用于裸机或 RTOS 系统的驱动程序;
可以使用 BSD API 在现有的 TCP/IP 堆栈上运行,例如 lwIP、Zephyr、Azure 等;
内置 TLS 1.3 ECC 堆栈,也可以使用外部 TLS 库 – mbedTLS、OpenSSL 或其他;
不依赖任何其他软件来实现网络。
一、Mongoose软件包
1、源码下载
Github:https://github.com/cesanta/mongoose/tree/master
2、修改mongoose.h
#define MG_ARCH MG_ARCH_RTTHREAD |
3、使能POSIX文件系统
![]() |
二、Mongoose文档
https://mongoose.ws/documentation/#user-guide
三、Mongoose SHA
1、CRC32
char data[] = "hello"; uint32_t crc = mg_crc32(0, data, sizeof(data)); |
2、MD5
mg_md5_ctx ctx; mg_md5_init(&ctx); mg_md5_update(&ctx, "data", 4); // hash "data" string mg_md5_update(&ctx, "more data", 9); // hash "more data" string nsigned char buf[16]; mg_md5_final(&ctx, buf); // `buf` is now MD5 hash |
3、SHA1
mg_sha1_ctx ctx;mg_sha1_init(&ctx); mg_sha1_update(&ctx, "data", 4); // hash "data" string mg_sha1_update(&ctx, "more data", 9); // hash "more data" string unsigned char buf[20]; mg_sha1_final(buf, &ctx); // `buf` is now SHA1 hash |
四、Mongoose TCP
1、TCP服务端
#include <rtthread.h>
#include <rtdevice.h>
#include <drv_common.h>
#include <arpa/inet.h>
#include <netdev.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "mongoose.h"
// Callback functions
static void on_listening(void) {
rt_kprintf("Server is listening\n");
}
static void on_accept(void) {
rt_kprintf("Client connected\n");
}
static void on_read(struct mg_connection *c, unsigned char *data, size_t len) {
rt_kprintf("Received data: %.*s\n", (int)len, data);
// Echo the received data back to the client
mg_send(c, data, len);
}
static void on_close(void) {
rt_kprintf("Client disconnected\n");
}
static void on_error(char *ev_data) {
rt_kprintf("Error: %s\n", ev_data);
}
// Event handler
static void event_handler(struct mg_connection *c, int ev, void *ev_data) {
switch (ev) {
case MG_EV_OPEN:
if (c->is_listening) {
on_listening();
}
break;
case MG_EV_ACCEPT:
on_accept();
break;
case MG_EV_READ:
on_read(c, (unsigned char *)c->recv.buf, c->recv.len);
c->recv.len = 0; // Clear the buffer
break;
case MG_EV_CLOSE:
on_close();
break;
case MG_EV_ERROR:
on_error((char *)ev_data);
break;
default:
break;
}
}
// Main function to run the TCP server
void run_tcp_server(const char *address) {
struct mg_mgr mgr;
struct mg_connection *connection;
// Initialize Mongoose manager
mg_mgr_init(&mgr);
// Start listening on the specified address
connection = mg_listen(&mgr, address, event_handler, NULL);
if (connection == NULL) {
rt_kprintf("Failed to start listening on %s\n", address);
mg_mgr_free(&mgr);
return;
}
rt_kprintf("Server listening on %s...\n", address);
// Main loop to poll events
while (1) {
mg_mgr_poll(&mgr, 1000);
}
// Cleanup
mg_mgr_free(&mgr);
}
#define NETDEV_NAME "e0"
int main(void)
{
struct netdev *netdev;
netdev = netdev_get_by_name(NETDEV_NAME);
if (netdev == RT_NULL) {
rt_kprintf("network interface device %s not found!\n", NETDEV_NAME);
return -1;
}
while(1) {
if(netdev_is_link_up(netdev)) {
run_tcp_server("192.168.0.105:6666");
}
rt_thread_delay(100);
}
return RT_EOK;
}
2、TCP客户端
#include <rtthread.h>
#include <rtdevice.h>
#include <drv_common.h>
#include <arpa/inet.h>
#include <netdev.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "mongoose.h"
// Callback functions
static void on_connected(void) {
rt_kprintf("Connected to server\n");
}
static void on_read(struct mg_connection *c, unsigned char *data, size_t len) {
rt_kprintf("Received data: %.*s\n", (int)len, data);
mg_send(c, data, len);
}
static void on_close(void) {
rt_kprintf("Connection closed\n");
}
static void on_error(char *ev_data) {
rt_kprintf("Error: %s\n", ev_data);
}
// Event handler
static void event_handler(struct mg_connection *c, int ev, void *ev_data) {
switch (ev) {
case MG_EV_CONNECT:
on_connected();
const char *welcome_message = "Hello, server!";
mg_send(c, welcome_message, strlen(welcome_message));
break;
case MG_EV_READ:
on_read(c, (unsigned char *)c->recv.buf, c->recv.len);
c->recv.len = 0; // Clear the buffer
break;
case MG_EV_CLOSE:
on_close();
break;
case MG_EV_ERROR:
on_error((char *)ev_data);
break;
default:
break;
}
}
// Main function to run the TCP client
void run_tcp_client(const char *address) {
struct mg_mgr mgr;
struct mg_connection *connection;
// Initialize Mongoose manager
mg_mgr_init(&mgr);
// Connect to the server
connection = mg_connect(&mgr, address, event_handler, NULL);
if (connection == NULL) {
rt_kprintf("Failed to connect to %s\n", address);
mg_mgr_free(&mgr);
return;
}
rt_kprintf("Connecting to %s...\n", address);
// Main loop to poll events
while (1) {
mg_mgr_poll(&mgr, 1000);
}
// Cleanup
mg_mgr_free(&mgr);
}
#define NETDEV_NAME "e0"
int main(void)
{
struct netdev *netdev;
netdev = netdev_get_by_name(NETDEV_NAME);
if (netdev == RT_NULL) {
rt_kprintf("network interface device %s not found!\n", NETDEV_NAME);
return -1;
}
while(1) {
if(netdev_is_link_up(netdev)) {
run_tcp_client("192.168.0.108:6666");
}
rt_thread_delay(100);
}
return RT_EOK;
}
五、Mongoose MQTT
1、MQTT客户端
#include <rtthread.h>
#include <rtdevice.h>
#include <drv_common.h>
#include <arpa/inet.h>
#include <netdev.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "mongoose.h"
static const char *s_url = "192.168.0.128:1883";
static const char *s_sub_topic = "mg/+/test"; // Subscribe topic
static const char *s_pub_topic = "mg/clnt/test"; // Publish topic
static int s_qos = 0; // MQTT QoS
// MQTT event callback
static void mqtt_event_handler(struct mg_connection *c, int ev, void *ev_data) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *)ev_data;
switch (ev) {
case MG_EV_MQTT_OPEN:
rt_kprintf(("%lu CONNECTED to %s", c->id, s_url));
// Subscribe to a topic after connection
struct mg_str subt = mg_str(s_sub_topic);
struct mg_mqtt_opts sub_opts;
memset(&sub_opts, 0, sizeof(sub_opts));
sub_opts.topic = subt;
sub_opts.qos = s_qos;
mg_mqtt_sub(c, &sub_opts);
rt_kprintf(("%lu SUBSCRIBED to %.*s", c->id, (int) subt.len, subt.buf));
// Publish a message
struct mg_str pubt = mg_str(s_pub_topic), data = mg_str("hello");
struct mg_mqtt_opts pub_opts;
memset(&pub_opts, 0, sizeof(pub_opts));
pub_opts.topic = pubt;
pub_opts.message = data;
pub_opts.qos = s_qos;
pub_opts.retain = false;
mg_mqtt_pub(c, &pub_opts);
rt_kprintf(("%lu PUBLISHED %.*s -> %.*s", c->id, (int) data.len, data.buf,
(int) pubt.len, pubt.buf));
break;
case MG_EV_MQTT_MSG:
rt_kprintf("Received MQTT message on topic '%.*s': %.*s\n",
(int)msg->topic.len, msg->topic.buf,
(int)msg->data.len, msg->data.buf);
break;
case MG_EV_CLOSE:
rt_kprintf("MQTT connection closed\n");
break;
case MG_EV_ERROR:
rt_kprintf("MQTT connection error\n");
break;
default:
break;
}
}
// Main function to run the MQTT client
void run_mqtt_client(const char *mqtt_server, const char *mqtt_client_id,
const char *mqtt_user, const char *mqtt_pass) {
struct mg_mgr mgr;
struct mg_connection *mqtt_conn;
// Initialize Mongoose manager
mg_mgr_init(&mgr);
// MQTT client options
struct mg_mqtt_opts mqtt_opts;
memset(&mqtt_opts, 0, sizeof(mqtt_opts));
mqtt_opts.client_id = mg_str(mqtt_client_id);
mqtt_opts.keepalive = 60;
mqtt_opts.qos = s_qos;
mqtt_opts.user = mg_str(mqtt_user);
mqtt_opts.pass = mg_str(mqtt_pass);
// Connect to MQTT broker
mqtt_conn = mg_mqtt_connect(&mgr, mqtt_server, &mqtt_opts, mqtt_event_handler, NULL);
if (mqtt_conn == NULL) {
rt_kprintf("Failed to connect to MQTT broker\n");
mg_mgr_free(&mgr);
return;
}
rt_kprintf("Connecting to MQTT broker...\n");
// Main loop to handle MQTT events
while (1) {
mg_mgr_poll(&mgr, 1000);
}
// Cleanup
mg_mgr_free(&mgr);
}
#define NETDEV_NAME "e0"
int main(void)
{
struct netdev *netdev;
netdev = netdev_get_by_name(NETDEV_NAME);
if (netdev == RT_NULL) {
rt_kprintf("network interface device %s not found!\n", NETDEV_NAME);
return -1;
}
while(1) {
if(netdev_is_link_up(netdev)) {
run_mqtt_client(s_url, "rtthread_client", "root", "dxf124213");
}
rt_thread_delay(100);
}
return RT_EOK;
}
作者:Xiangfu DING