Mongoose是一个用C编写的网络库。它为客户端和服务器模式实现TCP,UDP,HTTP,WebSocket,CoAP,MQTT的事件驱动的非阻塞API。

设计理念:

Mongoose有三个基本的数据结构:

struct mg_mgr 是一个事件管理器,保存所有活动的连接
struct mg_connection 描述一个连接
struct mbuf 描述数据缓冲区(接收或发送的数据)

连接可能是listening,inbound或outbound。通过调用mg_connect()创建outbound连接。listening连接是由mg_bind()创建的。inbound连接是通过listening连接接受后的连接。每个连接由struct mg_connection 结构描述,它具有许多字段,如套接字,事件处理函数,发送/接收缓冲区,标志等。

使用mongoose的应用程序应遵循事件驱动应用程序的标准模式:

1. 声明和初始化事件管理器:

 struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);

2. 创建连接。例如,服务器应用程序应该创建侦听连接:

 struct mg_connection *c = mg_bind(&mgr, "", ev_handler_function);
mg_set_protocol_http_websocket(c);

3. 通过调用循环创建一个事件mg_mgr_poll()循环:

for (;;) {
mg_mgr_poll(&mgr, );
}

mg_mgr_poll()迭代所有套接字,接受新连接,发送和接收数据,关闭连接并调用相应事件的事件处理函数。

内存缓冲区

每个连接有一个发送和接收缓冲区,分别是struct mg_connection::send_mbuf 和 struct mg_connection::recv_mbuf。当数据到达时,Mongoose将收到的数据附加到recv_mbuf并触发MG_EV_RECV 事件。用户可以通过调用输出函数之一来发送数据,如 mg_send()mg_printf()。输出功能将数据附加到send_mbuf。当Mongoose成功将数据写入套接字时,它将丢弃数据 struct mg_connection::send_mbuf并发送MG_EV_SEND事件。当连接关闭时,发送MG_EV_CLOSE事件。

事件处理函数

每个连接都有一个事件处理函数。该功能必须由用户实现。事件处理程序是Mongoose应用程序的关键元素,因为它定义了应用程序的行为。下面是一个事件处理函数:

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
switch (ev) {
/* Event handler code that defines behavior of the connection */
...
}
}
  • struct mg_connection *nc:已收到事件的连接。
  • int ev:事件编号,定义在mongoose.h。例如,当数据到达inbound连接时,ev将是MG_EV_RECV
  • void *ev_data:该指针指向事件特定的数据,它对于不同的事件具有不同的含义。例如,对于MG_EV_RECV事件, ev_dataint *指向从远程对等体接收并保存到接收IO缓冲区中的字节数的指针。ev_data每个事件描述的具体含义 。特定于协议的事件通常ev_data指向具有协议特定信息的结构。

注意:对于应用程序特定数据,struct mg_connection具有void *user_data占位符。Mongoose不使用该指针。事件处理程序可以存储任何类型的信息。

活动

Mongoose接受传入连接,读取和写入数据,并在适当时调用每个连接的指定事件处理程序。这是一个典型的事件序列:

outbound 连接: MG_EV_CONNECT -> (MG_EV_RECV, MG_EV_SEND, MG_EV_POLL...) -> MG_EV_CLOSE
inbound 连接: MG_EV_ACCEPT -> (MG_EV_RECV, MG_EV_SEND, MG_EV_POLL ...) -> MG_EV_CLOSE

以下是由Mongoose触发的核心事件列表(请注意,除了核心事件之外,每个协议都会触发特定于协议的事件):

  • MG_EV_ACCEPT:当listening连接接受新的服务器连接时发送。void *ev_dataunion 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()来丢弃已处理的数据,必要 时设置连接标志nc->flags(见struct mg_connection),并通过输出函数写入远程对等体的数据 mg_send()

    警告:Mongoose用于realloc()扩展接收缓冲区。用户有责任从接收缓冲区的开头丢弃已处理的数据,请注意mbuf_remove()上述示例中的调用。

  • MG_EV_SEND:Mongoose已经向远程对等体写入了数据,并丢弃了数据mg_connection::send_mbufvoid *ev_dataint *num_sent_bytes

    注意:Mongoose输出功能仅将数据附加到 mg_connection::send_mbuf。他们不做任何套接字写。实际的IO由mg_mgr_poll()完成。一个MG_EV_SEND事件是关于IO已经完成的通知。

  • MG_EV_POLL:发送到每个调用的所有连接mg_mgr_poll()。此事件可用于执行任何内务处理,例如检查某个超时是否过期并关闭连接或发送心跳消息等。

  • MG_EV_TIMER发送到连接如果mg_set_timer()被调用。

连接标志

每个连接都有一个flags位字段。一些标志由Mongoose设置,例如,如果用户使用udp://1.2.3.4:5678 地址创建出站UDP连接,Mongoose将MG_F_UDP为该连接设置一个标志。其他标志仅由用户事件处理程序设置,以告诉Mongoose如何行为。以下是由事件处理程序设置的连接标志列表:

  • MG_F_FINISHED_SENDING_DATA告诉Mongoose所有的数据已被追加到send_mbuf。一旦Mongoose将其发送到套接字,连接将被关闭。
  • MG_F_BUFFER_BUT_DONT_SEND告诉Mongoose将数据附加到send_mbuf 但是发送它,因为数据将被稍后修改,然后通过清除MG_F_BUFFER_BUT_DONT_SEND标志来发送。
  • MG_F_CLOSE_IMMEDIATELY 告诉Mongoose立即关闭连接,通常在发生错误后。
  • MG_F_USER_1MG_F_USER_2MG_F_USER_3MG_F_USER_4可以由开发者用来存储特定于应用的状态。

以下标志由Mongoose设置:

  • MG_F_SSL_HANDSHAKE_DONE 仅SSL,在SSL握手完成后设置。
  • MG_F_CONNECTINGmg_connect()连接处于连接状态, 但连接尚未完成后设置。
  • MG_F_LISTENING 设置为所有侦听连接。
  • MG_F_UDP 如果连接是UDP,请设置。
  • MG_F_IS_WEBSOCKET 设置如果连接是WebSocket连接。
  • MG_F_WEBSOCKET_NO_DEFRAG 如果用户想要关闭自动WebSocket框架碎片整理,应由用户设置。

构建选项

Mongoose源代码包含在包含所有支持的协议(模块)的功能的单个.c文件中。可以在编译时禁用模块,从而减少可执行文件的大小。这可以通过设置预处理程序标志来实现。此外,一些预处理器标志可用于调整内部Mongoose参数。

要在编译期间设置预处理器标志,请使用-D <PREPROCESSOR_FLAG> 编译器选项。例如,要禁用MQTT和CoAP,请编译my_app.c这样的应用程序(假定为UNIX系统):

 $ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_COAP

mongoose 开源http库的更多相关文章

  1. mongoose 开源http库(2) --HTTP服务示例

    要创建HTTP服务器,请按照以下格式: 通过调用mg_bind()或mg_bind_opt()创建侦听连接 调用mg_set_protocol_http_websocket()创建listening连 ...

  2. Pugixml一种快速解析XML文件的开源解析库

    Pugixml是一个轻量级的C++ XML开源解析库,DOM形式的解析器.接口和丰富的遍历和修改操作,快速的解析,此外支持XPath1.0实现数据查询,支持unicode编码: 使用Pugixml可通 ...

  3. iOS流行的开源代码库

    本文介绍一些流行的iOS的开源代码库 1.AFNetworking 更新频率高的轻量级的第三方网络库,基于NSURL和NSOperation,支持iOS和OSX.https://github.com/ ...

  4. 从Google开源RE2库学习到的C++测试方案

    最近因为科研需求,一直在研究Google的开源RE2库(正则表达式识别库),库源码体积庞大,用C++写的,对于我这个以前专供Java的人来说真的是一件很痛苦的事,每天只能啃一点点.今天研究了下里面用到 ...

  5. 爆料喽!!!开源日志库Logger的剖析分析

    导读 Logger类提供了多种方法来处理日志活动.上一篇介绍了开源日志库Logger的使用,今天我主要来分析Logger实现的原理. 库的整体架构图 详细剖析 我们从使用的角度来对Logger库抽茧剥 ...

  6. 爆料喽!!!开源日志库Logger的使用秘籍

    日志对于开发来说是非常重要的,不管是调试数据查看.bug问题追踪定位.数据信息收集统计,日常工作运行维护等等,都大量的使用到.今天介绍著名开源日志库Logger的使用,库的地址:https://git ...

  7. Android开源图表库介绍

    XCL-Charts XCL-Charts V1.8     Android开源图表库(XCL-Charts is a free charting library for Android platfo ...

  8. C++100款开源界面库[转]

    (声明:Alberl以后说到开源库,一般都是指著名的.或者不著名但维护至少3年以上的.那些把代码一扔就没下文的,Alberl不称之为开源库,只称为开源代码.这里并不是贬低,像Alberl前面那个系列的 ...

  9. [C#技术] .NET平台开源JSON库LitJSON的使用方法

    一个简单示例: String str = "{’name’:’cyf’,’id’:10,’items’:[{’itemid’:1001,’itemname’:’hello’},{’itemi ...

随机推荐

  1. DeepWalk 安装指南

    DeepWalk 安装指南 创建 conda 虚拟环境 conda create -n deepwalk pip python=3.5 conda activate deepwalk 安装 deepw ...

  2. leetcode 160相交链表

    暴力解法当然可以遍历两个链表,不过time O(mn) space O(1)暂且不说, 方法一:双指针, time O(m+n),space O(1) 可以对比判断环形链表的快慢指针法. 这种方法构思 ...

  3. Hibernate框架 初识 ORM概念

    Hibernate概述 Hibernate是一个ORM(对象关系映射)映射框架,它的核心思想就是在底层对JDBC进行了一次封装. 什么是框架 IT语境中的框架,特指为解决一个开放性问题而设计的具有一定 ...

  4. 内核参数和GRUB&GRUB2

    内核允许您使用各种选项运行系统.示例列表https://www.kernel.org/doc/html/v4.14/ad...eters.html 如何为以下项添加选项:_______________ ...

  5. 【Deep Learning Nanodegree Foundation笔记】第 0 课:课程计划

    第一周 机器学习的类型,以及何时使用机器学习 我们将首先简单介绍线性回归和机器学习.这将让你熟悉这些领域的常用术语,你需要了解的技术进展,并了解深度学习在更大的机器学习背景中的位置. 直播:线性回归 ...

  6. C++ 优先队列 priority_queue

    平时定义的时候,直接上就完事了: priority_queue<int>Q; 默认大根堆. 之前很菜的时候不知道小根堆怎么写,还在考场上干过加个负号甩到大根堆里面去的蠢事. 它的完整形式呢 ...

  7. USACO3.3 Home on the Range【思维】

    做完之后看到题解里面很多bfs,dfs,甚至还有dp? 写了一个不知道怎么称呼它的方法,暂且叫他乱搞吧. 用数组a[][]预处理出以当前行作为最底层,这一列从上往下的最长的1的长度. 如果这个格子为0 ...

  8. 【电子电路技术】短波红外InGaAs探测器简析

    核心提示: 红外线是波长介于微波与可见光之间的电磁波,波长在0.75-1000μm之间,其在军事.通讯.探测.医疗等方面有广泛的应用.目前对红外线的分类还没有统一的标准,各个专业根据应用的需要,有着自 ...

  9. Java基础/Java异常

    Java异常 1.异常的分类: ① 非运行时异常(Checked Exception) Java中凡是继承自Exception但不是继承自RuntimeException的类都是非运行时异常 ② 运行 ...

  10. MVC学习途径

    博客园专题:http://kb.cnblogs.com/zt/mvc/ MVC源码:http://www.codeplex.com/site/search?projectSearchText=mvc ...