文章目录

  • Mongoose库
    • 设计理念
    • 缓冲区
    • 事件处理函数
    • 事件
    • 连接flags
  • Http示例
    • RESTful Server

Mongoose是C语言网络库,为TCP、UDP、HTTP、WebSocket、CoAP、MQTT实现了事件驱动型的非阻塞api。

Mongoose库

Mongoose是出名的嵌入式网络编程库(https://github.com/cesanta/mongoose);只需微小的静态和运行时占用空间,实现了:

  • 普通TCP、普通UDP、SSL/TLS(单向或双向)、客户端和服务器。
  • http客户端和服务器。
  • WebSocket客户端和服务器。
  • MQTT客户机和服务器。
  • CoAP客户端和服务器。
  • DNS客户端和服务器。
  • 异步DNS解析程序。

设计理念

Mongoose的三个基本数据结构:

struct mg_mgr;///事件管理器,保存所有的活动链接
struct mg_connection;///描述一个链接
struct mbuf;///接收和发送的数据

每个链接都使用mg_connection进行描述,一个连接可以是:

  • outbound(出站)链接:通过调用mg_connect()产生;
  • listening(监听)链接:通过调用mg_bind()产生;
  • inbound(入站)链接:listening链接所收到的链接;

Mongoose应用应遵循事件驱动模式,通过mg_mgr_poll()遍历所有的套接字,接受新链接、发送、接收数据、关闭链接;并为各自的事件调用事件处理函数。

struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);    // 创建并初始化事件管理器
struct mg_connection *c = mg_bind(&mgr, "80", ev_handler_function);
mg_set_protocol_http_websocket(c);  //创建链接
for (;;) {  //通过调用mg_mgr_pool()创建事件循环mg_mgr_poll(&mgr, 1000);
}

缓冲区

每个连接都有一个发送和接收缓冲区:

  • mg_connection::recv_mbuf:将接收到的数据加到recv_mbuf后面,并触发一个MG_EV_RECV事件;
  • mg_connection::send_mbuf:用户发送数据(mg_send()mg_printf())时,输出函数将数据追加到send_mbuf;成功地将数据写到socket后,丢弃缓冲区中的数据并触发一个MG_EV_SEND事件;

连接关闭后,触发一个MG_EV_CLOSE事件。

事件处理函数

每个链接都有其与之相关的事件处理函数,是数据处理的关键元素。

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {switch (ev) {/* Event handler code that defines behavior of the connection */...}
}

参数说明:

  • mg_connection *nc:触发事件的连接;内部有void *user_data字段,可保存用户自定义信息;
  • int ev:事件编号;
  • void *ev_data : 事件数据指针(不同的事件有不同的意义)

事件

Mongoose接受传入连接、读取和写入数据,并在适当时机触发对应指定事件:

  • 出站连接:MG_EV_CONNECT -> (MG_EV_RECV, MG_EV_SEND, MG_EV_POLL …) -> MG_EV_CLOSE
  • 入站连接:MG_EV_ACCEPT -> (MG_EV_RECV, MG_EV_SEND, MG_EV_POLL …) -> MG_EV_CLOSE

核心事件说明:

  • MG_EV_ACCEPT: 接收到新连接,void *ev_data是远程端的union socket_address
  • MG_EV_CONNECT: 当mg_connect()创建了一个新出站链接时(无论连接是否成功),void *ev_dataint *success;当success是0,则连接已经建立,否则包含一个错误码(mg_connect_opt()函数来查看错误码)。
  • MG_EV_RECV:接收数据并追加到recv_mbuf时触发。void *ev_dataint *num_received_bytes(接收到的数据长度)。通常,事件处理函数应通过nc->recv_mbuf检查接收数据,并通过mbuf_remove()丢弃已处理的数据(用户有责任从接收缓冲区丢弃已处理的数据)。
  • MG_EV_SEND: 已将数据写入到socket中,并且已经丢弃写入到mg_connection::send_mbuf的数据;void *ev_dataint *num_sent_bytes
  • MG_EV_POLL:在每次调用mg_mgr_poll()时触发。该事件被用于做任何事情,例如,检查某个超时是否已过期并关闭连接或发送心跳消息等。
  • MG_EV_TIMER: 当mg_set_timer()调用后触发。

连接flags

每个链接都有flags位域。

由事件处理程序设置的链接flags列表:

  • MG_F_FINISHED_SENDING_DATA:告诉mongoose所有数据已经追加到send_mbuf,只要mongoose将数据写入socket,此链接就会关闭。
  • MG_F_BUFFER_BUT_DONT_SEND:告诉mongoose追加数据到send_mbuf,但数据不要马上发送,因为此数据稍后会被修改。然后通过清除MG_F_BUFFER_BUT_DONT_SEND标志将数据发送出去。
  • MG_F_CLOSE_IMMEDIATELY:告诉mongoose立即关闭链接,通常在产生错误后发送此事件。
  • MG_USER_1,MG_USER_2,MG_USER_3,MG_USER_4:开发者可用它来存储特定应用程序的状态

由mongoose设置的flags:

  • MG_F_SSL_HANDSHAKE_DONE:ssl握手完成时设置;
  • MG_F_CONNECTING:在mg_connect()调用后链接处于链接状态,但未完成链接时设置;
  • MG_F_LISTENING:在监听中;
  • MG_F_UDP:链接是udp时设置;
  • MG_F_WEBSOCKET:链接是websocket时设置;
  • MG_F_WEBSOCKET_NO_DEFRAG:如果用户想关闭websocket的自动帧碎片整理功能,则由用户设置此标记。

Http示例

HTTP请求中主要消息格式为:

struct http_message {struct mg_str message; /* Whole message: request line + headers + body */struct mg_str body;    /* Message body. 0-length for requests with no body *//* HTTP Request line (or HTTP response line) */struct mg_str method; /* "GET" */struct mg_str uri;    /* "/foo/bar" */struct mg_str proto;  /* "HTTP/1.1" -- for both request and response *//* For responses, code and response status message are set */int resp_code;struct mg_str resp_status_msg;/** Query-string part of the URI. For example, for HTTP request*    GET /foo/bar?param1=val1&param2=val2*       |   uri  |     query_string     |** Note that question mark character doesn't belong neither to the uri,* nor to the query_string*/struct mg_str query_string;/* Headers:默认最多40个,可根据需要修改 */struct mg_str header_names[MG_MAX_HTTP_HEADERS];struct mg_str header_values[MG_MAX_HTTP_HEADERS];
};

RESTful Server

对于Http请求,MG_EV_HTTP_MSG为接收到消息时触发的事件。

mg_http_message中存放的是Http请求的消息,通过mg_http_reply来应答Http请求。

std::string getMgStr(struct mg_str str) {return std::string(str.ptr, str.len);
}// We use the same event handler function for HTTP and HTTPS connections
// fn_data is NULL for plain HTTP, and non-NULL for HTTPS
static void funCallback(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {std::cout << "Connect from: " << c->peer.ip << ":" << c->peer.port << ", type: " << ev << std::endl;if (ev == MG_EV_ACCEPT && fn_data != NULL) {struct mg_tls_opts opts = {//.ca = "ca.pem",         // Uncomment to enable two-way SSL.cert = "server.pem",    // Certificate PEM file.certkey = "server.pem", // This pem contains both cert and key};mg_tls_init(c, &opts);} else if (ev == MG_EV_HTTP_MSG) {struct mg_http_message *hm = (struct mg_http_message *) ev_data;std::cout << "Http request: Method=" << getMgStr(hm->method) << ", URI=" << getMgStr(hm->uri)<< ", query=" << getMgStr(hm->query) << ", proto=" << getMgStr(hm->proto) << std::endl;std::cout << "Request body: " << getMgStr(hm->body) << std::endl;if (mg_vcmp(&hm->uri, "/api/f1") == 0) {// Serve RESTjson jData = json::parse(hm->body.ptr, hm->body.ptr + hm->body.len);std::cout << "##iterate data\n";for (auto it:jData) {std::cout << "value: " << it << '\n';}std::cout << "##iterate items\n";for (auto &el:jData.items()) {std::cout << "Key: " << el.key() << ", value: " << el.value() << '\n';}mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);} else if (mg_http_match_uri(hm, "/api/f2/*")) {mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len, hm->uri.ptr);} else {// struct mg_http_serve_opts opts = {.root_dir = s_root_dir};// mg_http_serve_dir(c, ev_data, &opts);mg_http_reply(c, 200, "", "Unknown request\n"); // Serve REST}}(void) fn_data;
}void startHttpServer() {struct mg_mgr mgr;       // Event managermg_log_set("2");         // Set to 3 to enable debugmg_mgr_init(&mgr);       // Initialise event managermg_http_listen(&mgr, s_http_addr, funCallback, NULL);   // Create HTTP listener
//    mg_http_listen(&mgr, s_https_addr, funCallback, (void *) 1); // HTTPS listenerfor (;;)mg_mgr_poll(&mgr, 1000); // Infinite event loopmg_mgr_free(&mgr);
}

[C++]-网络库mongoose简介相关推荐

  1. muduo网络库:18---muduo简介之(muduo库的由来、编译安装、目录结构、代码结构、线程模型)

    一.由来 2010年3月陈硕先生写了一篇<学之者生,用之者死--ACE历史与简评>(文章参阅:https://blog.csdn.net/Solstice/article/details/ ...

  2. 网络增强现实开发简介 Introduction to Web AR development

    搭配webXR.mindAR.three.js和tensorflow.js 你会学到: 获得构建不同类型的网络增强现实应用程序的实践经验,包括图像效果.人脸效果和世界效果 获得关于增强现实如何在网络浏 ...

  3. Py之tornado:tornado库的简介、安装、使用方法之详细攻略

    Py之tornado:tornado库的简介.安装.使用方法之详细攻略 目录 tornado库的简介 tornado库的安装 tornado库的使用方法 1.简单的Tornado的"Hell ...

  4. Py之face_alignment:face_alignment库的简介、安装、使用方法之详细攻略

    Py之face_alignment:face_alignment库的简介.安装.使用方法之详细攻略 目录 face_alignment库的简介 1.指定在CPU / GPU上运行 2.使用特定的面部检 ...

  5. Py之scikit-learn:机器学习Sklearn库的简介、安装、使用方法(ML算法如何选择)、代码实现之详细攻略

    Py之scikit-learn:机器学习Sklearn库的简介.安装.使用方法.代码实现之详细攻略 目录 scikit-learn的简介 scikit-learn的安装 scikit-learn的使用 ...

  6. Py之dlib:Python库之dlib库的简介、安装、使用方法详细攻略

    Py之dlib:Python库之dlib库的简介.安装.使用方法详细攻略 目录 dlib库的简介 dlib库的安装 dlib库的使用函数 0.利用dlib.get_frontal_face_detec ...

  7. 技术实践 | 聊聊网易云信的信令网络库实践

    导读:信令作为实时音视频技术架构中的重要一环,是对建立实时音视频通信起到关键桥梁性的作用. 文|丁永锋 网易云信资深客户端开发工程师 本文将从信令的概念着手,分享在网易云信新一代音视频技术架构下,信令 ...

  8. XMNetworking 网络库的设计与使用

    2019独角兽企业重金招聘Python工程师标准>>> XMNetwoking 是我们团队开源的一个网络库,详见:GitHub XMNetworking 是一个轻量的.简单易用但功能 ...

  9. Py之scikit-learn:机器学习sklearn库的简介、六大基本功能介绍(数据预处理/数据降维/模型选择/分类/回归/聚类)、安装、使用方法(实际问题中如何选择最合适的机器学习算法)之详细攻略

    Py之scikit-learn:机器学习sklearn库的简介(组件/版本迭代).六大基本功能介绍(数据预处理/数据降维/模型选择/分类/回归/聚类).安装.使用方法(实际问题中如何选择最合适的机器学 ...

最新文章

  1. java datahandler_Java Web Services:使用DataHandler类发送文件
  2. 解决使用requests_html模块,req.html.render()下载chromium速度慢问题
  3. 在实际管理中学习管理
  4. 五、oracle 表的管理
  5. Couchbase概述
  6. 实现 通过数据库里一个字段值相等 则把 他合为一条数据
  7. 将一个BYTE数组转换成16进制字符串和10进制字符串格式
  8. WLAN 无线网络 02 - 频率、信道、编码、调制
  9. 斐波那契数列的时间复杂度
  10. kafka--Struct Streaming--console案例入门
  11. JavaScript 遗漏知识再整理;错误处理,类型转换以及获取当前时间、年份、月份、日期;...
  12. 2019年8月19日矩阵
  13. 建筑工程PPP项目财务风险控制探析
  14. 0x0000006b蓝屏解决方法 - WIN7
  15. WSL下Kali 2021 启用mysql服务并通过主机连接
  16. 【历史上的今天】6 月 1 日:Napster 成立;MS-DOS 原作者出生;谷歌出售 Google SketchUp
  17. ASP.NET 安全认证(二)【转】
  18. 可视化大屏自适应效果
  19. 如何将Ai文件转换成PDF文件
  20. workon 未找到命令

热门文章

  1. 在mac上关闭microsoft的自动更新
  2. MRTG流量监控图配置说明
  3. solrj html过滤,Solr7.4.0的API(Solrj)操作
  4. Xgboost通俗理解
  5. ifconfig不显示ip,虚拟机静态IP设置方法
  6. 【Spring】Bean生命周期源码分析 总结
  7. 人员与叉车防撞预警方案
  8. 如何自动翻译 WordPress 网站(快速且成本最低)
  9. 今天的爸爸急中生智的蜡笔小新
  10. python抓取几大票房统计系统数据的之猫眼电影