1、github项目地址:https://github.com/cesanta/mongoose
2、使用手册:https://mongoose.ws/documentation
3、https://mongoose.ws
Mongoose是一个C/C++的网络库,它为TCP、UDP、HTTP、WebSocket、MQTT实现了事件驱动的、非阻塞的API。
做一个简单的HTTP服务端,可以在浏览器中显示hello world
#include "mongoose.h"
static void fn(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_print_esc, 0, "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
}
}
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
mg_mgr_init(&mgr); // Init manager
mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr); // Setup listener
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr); // Cleanup
return 0;
}
主函数中,首先要实例化一个对象,用来管理事件。
然后初始化事件管理结构体,创建http监听,循环监听连接的客户端。
最后退出程序时清除事件管理结构体
fn是http事件的回调函数,在该函数中首先判断是否是http事件,然后判断URI,如果匹配成功则在网页中显示相应的内容,否则显示根目录中的内容
编写cmake文件
cmake_minimum_required(VERSION 3.16)
project(mongoose_test)
add_executable(mongoose_test)
target_sources(mongoose_test PRIVATE main.c mongoose/mongoose.c)
target_include_directories(mongoose_test PRIVATE mongoose)
第1行:版本要求
第2行:工程名
第3行:生成的可执行文件名
第4行:需要的源码文件
第5行:包含的目录
编译,运行,在浏览器中输入ip地址和端口号,则在网页中会显示当前目录中的内容,这是因为在本地并没有"/api/hello"这个文件。所以如果想显示helloworld则需要在本地写一个html文件,并将路径写到"/api/hello"这个位置。
将 if (mg_http_match_uri(hm, "/api/hello"))
修改为if (mg_http_match_uri(hm, "html/index.html"))
并在工程的根目录下写一个index.html文件(文件名是index.html时,直接输入ip地址和端口号即可,此时的http发送的请求就是请求index.html文件)
<html>
<head>
<meat charset="utf-8">
<title> mongoose test title>
head>
<body>
<b><font color="blue"> hello world font>b>
body>
html>
编译执行,在浏览器中输入http://0.0.0.0:8000/,则显示下图
事件管理结构,包含活动连接列表以及一些管理信息。
struct mg_mgr
struct mg_mgr {
struct mg_connection *conns; // List of active connections
struct mg_dns dns4; // DNS for IPv4
struct mg_dns dns6; // DNS for IPv6
int dnstimeout; // DNS resolve timeout in milliseconds
unsigned long nextid; // Next connection ID
void *userdata; // Arbitrary user data pointer
};
struct mg_connection {
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
struct mg_mgr *mgr; // Our container
struct mg_addr loc; // Local address
struct mg_addr rem; // Remote address
void *fd; // Connected socket, or LWIP data
unsigned long id; // Auto-incrementing unique connection ID
struct mg_iobuf recv; // Incoming data
struct mg_iobuf send; // Outgoing data
mg_event_handler_t fn; // User-specified event handler function
void *fn_data; // User-specified function parameter
mg_event_handler_t pfn; // Protocol-specific handler function
void *pfn_data; // Protocol-specific function parameter
char data[MG_DATA_SIZE]; // Arbitrary connection data, MG_DATA_SIZE defaults to 32 bytes
void *tls; // TLS specific data
unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection
unsigned is_resolving : 1; // Non-blocking DNS resolve is in progress
unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection
unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared
unsigned is_resp : 1; // Response is still being generated
unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
}
初始化事件管理结构体
mg_mgr_init()
函数原型:
void mg_mgr_init(struct mg_mgr *mgr);
主要功能:
将活动连接列表设置为NULL
设置IPv4和IPv6的默认DNS服务器
设置默认DNS查找超时时间
参数:
mgr:指向需要初始化的mg_mgr结构的指针
返回值:
无返回值
执行单个轮询
mg_mgr_poll()
函数原型:
void mg_mgr_poll(struct mg_mgr *mgr, int ms);
主要功能:
1. 查看是否有传入数据。如果有,读入c->recv,发送MG_EV_READ事件
2. 查看c->send缓冲区是否有数据,有写入它,发送MG_EV_WRITE事件
3. 如果连接正在侦听,则接受传入的连接(如果有),并向其发送MG_EV_ACCEPT事件
4. 发送MG_EV_POLL事件
参数:
mgr:要使用的事件管理器
ms: 超时时间(ms为单位)
返回值:
无返回值
关闭连接
mg_mgr_free()
函数原型:
void mg_mgr_free(struct mg_mgr *mgr);
主要功能:
关闭所有连接,并释放所有资源
参数:
mgr:要进行清理事件管理器
返回值:
无返回值
struct mg_http_message结构体
struct mg_http_message()
函数原型:
struct mg_http_message {
struct mg_str method, uri, query, proto; // Request/response line
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
struct mg_str body; // Body
struct mg_str message; // Request line + headers + body
};
主要功能:
结构表示HTTP消息
创建http listener
mg_http_listen()
函数原型:
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
主要功能:
创建HTTP侦听器
参数:
mgr:事件管理结构体
url:指定要监听的本地IP地址和端口,例如http://0.0.0.0:8000
fn:事件处理函数
fn_data:一个任意指针,在调用事件处理程序时作为fn_data传递。该指针也以c->fn_data的形式存储在连接结构中
返回值:
指向已创建连接的指针,如果出现错误,则为NULL
struct mg_http_serve_opts
struct mg_http_serve_opts
函数原型:
struct mg_http_serve_opts {
const char *root_dir; // Web root directory, must be non-NULL
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
const char *extra_headers; // Extra HTTP headers to add in responses
const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
const char *page404; // Path to the 404 page, or NULL by default
struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
};
主要功能:
传递给mg_http_serve_dir()和mg_http_serve_file()的结构,它驱动这两个函数的行为
mg_http_serve_dir()
mg_http_serve_dir()
函数原型:
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
主要功能:
根据给定的选项提供静态文件
参数:
c:连接使用
hm:HTTP消息,应该被服务
options:服务选项。注意选项。Root_dir可以选择接受额外的逗号分隔的uri=path对,
返回值:
无返回值
注意
为了启用SSI,您需要设置-DMG_ENABLE_SSI=1构建标志
避免使用 "../",在root_dir目录下。如果需要引用上级目录,请使用绝对路径
匹配URI
mg_http_match_uri()
函数原型:
bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob);
主要功能:
检查HTTP请求是否匹配给定的glob模式
参数:
hm:要匹配的HTTP消息
glob:模式,要匹配地址
返回值:
如果HTTP请求匹配给定的glob模式,则为True;假的,否则
mg_http_reply()
mg_http_reply()
函数原型:
void mg_http_reply(struct mg_connection *c, int status_code,
const char *headers, const char *body_fmt, ...);
主要功能:
使用printf()语义发送简单的HTTP响应。
该函数根据body_fmt格式设置响应体,并自动添加正确的Content-Length报头。额外的头可以通过headers参数传递。
参数:
c:连接使用
status_code:HTTP响应码
headers:额外的头,默认为NULL。如果不是NULL,必须以\r\n结尾
fmt:HTTP正文的格式字符串,采用printf语义
返回值:
无返回值