ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-05-17 10:56:54  阅读:266  来源: 互联网

标签:mg ev MG mgr Unix 源码 Mongoose EV


简述: 

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 */    ...
  }
}

典型的事件序列如下:

  • 对于客户端: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

以下为Mongoose的核心事件:

  • MG_EV_ACCEPT:当accept到一个新的连接请求时触发该事件,ev_data 为socket_address 联合体
  • MG_EV_CONNECT:当使用mg_connect() 创建连接套接字时触发该事件,ev_data 为int *success,success为0表示成功,否则为失败的errno
  • MG_EV_RECV:接收到新的数据,void *ev_data 是接收到的字节数,接收到应该使用recv_mbuf来获取数据,使用mg_send()发送数据。Mongoose 使用realloc来扩展接收缓冲区,但是需要由用户删除已接收的数据——比如mbuf_remove()。
  • MG_EV_SEND:Mongoose 已经将(int *)ev_data 的数据写到了远端并将数据从send_mbuf中删除。mg_send()并不发送数据,只是将数据追加到缓冲区,正真的IO操作由mg_mgr_poll()完成。
  • MG_EV_POLL:该事件被发送给所有的已连接套接字,它可以被用来作任何持续性的事务,比如检查某个连接是否已经超时或者关闭、过期,或者用来发送心跳消息。
  • MG_EV_TIMER:当mg_set_timer() 被调用时被用来发送给指定的connection

连接标记位
每个连接都有自己的标记位,比如当创建一个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 设定:

  • MG_F_SSL_HANDSHAKE_DONE SSL:只有在SSL连接中才会设置,当SSL的握手完成时设定
  • MG_F_CONNECTING:在调用mg_connect() 后但是连接还没有完成时设置
  • MG_F_LISTENING:为所有监听套接字设置
  • MG_F_UDP:如果是UDP协议则设置
  • MG_F_IS_WEBSOCKET:如果是网络套接字则设置
  • MG_F_WEBSOCKET_NO_DEFRAG:由用户希望关闭自动的websocket框架碎片整理时设置

编译选项:
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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有