编程语言
首页 > 编程语言> > Unix网络编程——Mongoose开源项目源码解读(1):概述

Unix网络编程——Mongoose开源项目源码解读(1):概述

作者:互联网

简述: 

Mongoose前身为shttpd,使用标准C/C++编写而成,转为嵌入式设备设计的,支持跨平台的网络服务器库。Mongoose实现了非阻塞式事件驱动API,支持TCP, UDP, HTTP, WebSocket, CoAP, MQTT。

Mongoose的三个基本结构体:

struct mg_mgr;           // 持有所有活动的连接的事件管理器struct mg_connection ;   // 用于连接的套接字状态的描述struct mbuf ;            // 用于接收和发送数据缓存的描述

声明与初始化事件管理器

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_poll(&mgr, 1000);
 }

收发缓冲区
每个连接都有自己的收发缓冲区struct mbuf,当Mongoose 接收到数据时数据被追加到接收缓冲区并触发一个MG_EV_RECV 事件。当需要发送数据时,只需要使用 mg_send()或者mg_printf()将数据追加到发送缓冲区,当数据发送成功,Mongoose 将数据从发送缓冲区删除并发送一个MG_EV_SEND事件。当连接关闭时,触发MG_EV_CLOSE事件。以下为mbuf的定义:

/* Memory buffer descriptor */struct mbuf {  char *buf;   /* Buffer pointer */
  size_t len;  /* Data length. Data is located between offset 0 and len. */
  size_t size; /* Buffer size allocated by realloc(1). Must be >= len */};

事件及事件处理函数
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 */    ...
  }
}

典型的事件序列如下:

以下为Mongoose的核心事件:

连接标记位
每个连接都有自己的标记位,比如当创建一个UDP连接时,Mongoose 将为这个连接的标记为设置为MG_F_UDP。

以下标记为用户设定:
- MG_F_FINISHED_SENDING_DATA:告诉Mongoose 数据已经全部存放到了发送缓冲区,当Mongoose 将数据发送完毕时,主动关闭连接。
- MG_F_BUFFER_BUT_DONT_SEND :告诉Mongoose 只将数据追加到缓冲区但是不要发送数据,因为数据之后可能会被修改,当MG_F_BUFFER_BUT_DONT_SEND标记位被清除时数据再被发送
- MG_F_CLOSE_IMMEDIATELY :告诉Mongoose 立马关闭连接,一般在出错的时候设置
- MG_F_USER_1, MG_F_USER_2, MG_F_USER_3, MG_F_USER_4:用户自定义,用来存放应用的指定状态

以下标记由Mongoose 设定:

编译选项:
Mongoose 源代码由单一的c文件构成,Mongoose 所支持的协议都由它提供。在编译时Mongoose 可以去除不需要的功能以减小执行文件的大小。比如可以使用-D MG_DISABLE_MQTT -D MG_DISABLE_COAP去除代码中的MQTT和CoAP的支持代码。
linux下的编译样例:

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

Mongoose 的使用样例:
1.将mongoose.c 和mongoose.h拷贝到你的工程目录下
2.使用mongoose提供的API编写工程,例如my_app.c
3.编译工程:cc my_app.c mongoose.c

#include "mongoose.h"  // Include Mongoose API definitions// Define an event handler functionstatic void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {  struct mbuf *io = &nc->recv_mbuf;  switch (ev) {    case MG_EV_RECV:      // This event handler implements simple TCP echo server
      mg_send(nc, io->buf, io->len);  // Echo received data back
      mbuf_remove(io, io->len);      // Discard data from recv buffer
      break;    default:      break;
  }
}int main(void) {  struct mg_mgr mgr;

  mg_mgr_init(&mgr, NULL);  // Initialize event manager object

  // Note that many connections can be added to a single event manager
  // Connections can be created at any point, e.g. in event handler function
  mg_bind(&mgr, "1234", ev_handler);  // Create listening connection and add it to the event manager

  for (;;) {  // Start infinite event loop
    mg_mgr_poll(&mgr, 1000);
  }

  mg_mgr_free(&mgr);  return 0;
}

               

标签:mg,ev,MG,mgr,Unix,源码,Mongoose,EV
来源: https://blog.51cto.com/u_6650004/2780444