源码下载地址:https://github.com/cesanta/mongoose
Mongoose是用C语言写的一个网络库,它是嵌入式程序开发的瑞士军刀。它实现了TCP、UDP、HTTP、WebSocket、CoAP、MQTT客户端和和服务器APIs的非阻塞事件-驱动模式。功能包括:
简单的TCP,简单UDP,SSL/TLS(一种或者两种方法),客户端和服务器
HTTP客户端和服务器
WebSocket 客户端和服务器
MQTT客户端和服务器
CoAP客户端和服务器
DNS客户端和服务器
异步DNS的解决者
Mongoose有这些基本的数据结构:
连接可以是监听(Listening),外联(outbound),连进来(inbound)的任意一种。连出连接(outboud connection)用mg_connect()建立。监听连接(Listening connections)用mg_bind()建立。联入连接(inbound connections)通过listening connection接受.每个连接都是通过结构struct mg_connection来描述的。这个结构有类似sokcet,事件句柄,发送和接收缓冲区,标志。等等字段。
一个用Mongoose开发的程序应该遵循一个标准事件-驱动模式。
strcut mg_mgr mgr;
mg_mgr_init(&mgr,NULL);
2.建立连接:例如一个服务程序应该建立一个监听连接(listening connetcions)
struct mg_connection *c=mg_bind(&mgr,"80",ev_handler_function);
mg_set_protocol_http_websocket(c);
3.在一个循环中通过mg_mgr_pool()建立一个事件循环。
for(;;)
{
mg_mgr_pool(&mg,1000);
}
mg_mgr_pool()迭代所有的sockets,接受新的连接,发送和接收数据,关闭连接,调用指定的事件的回调函数。更详细的例子,请看 Usage Example,实现了TCP echo服务端。
每个连接(connection)都分别有一个发送和接收缓冲区,struct mg_connection::send_mbuf和strcut mg_connection::recv_mbuf,当数据到达后,Mongoose追加接收到的数据到recv_mbuf并且触发MG_EV_RECV事件。用户可以通过其中一个输出函数发送应答数据,比如:mg_send()或者mg_printf().输出函数追加数据到send_mbuf,.当Mongoose成功写数据到socket,mongoose从struct mg_connection::send_mbuf清除数据,并且发送MG_EV_SEND事件。当连接关闭后,MG_EV_CLOSE事件被发送。
每个连接(connection)都有要给关联的事件句柄函数(even handler function),用户必须自己实现在这个函数。事件函数是Mongoose程序的钥匙元素,因为他定义了程序的行为。如下是一个事件函数的样子(even handler function):
static void ev_handler(sturct mg_connection* nc,int ev,void* ev_data)
{
switch(ev)
{
/*定义这个连接的事件句柄函数的行为*/
}
}
struct mg_connection* nc:已经收到事件的连接(connection)
int ev:事件代码,在mongoose.h中定义,例如:连入连接的数据到达:ev是MG_EV_RECV
void* ev_data:这个指针指向事件特定的数据,并且不同的事件代码表示不同的意思。例如对于MG_EV_RECV事件,ev_data是一个int*指针,执向的内容是从远端发来的数据,并且已经保存到接收缓冲区的字节数量。ev_data准确的意思是根据具体的事件确定。每个协议指定的事件通常ev_data指针指向要给结构,该结构容纳协议指定的信息。
注意:struct mg_connection 有一个void* user_data ,他是一个程序指定数据的空间,Mongoose不能用这个指针。事件句柄能在这里存储任何他感兴趣的信息。
Mongoose接受连接进来的连接,为每个连接执行读数据,写数据和调用指定的事件句柄。合适的事件序列如下:
以下是被Mongoose出发的核心事件列表(请注意,除了核心事件之外,每个协议都会触发特定于协议的事件)
警告:Mongoose使用realloc()去扩大接收缓冲区,用户有责任从接收缓冲区开始处丢弃处理过的数据,注意, mbuf_remove()调用在上面的例子里。
NOTE:Mongoose输出函数 仅仅是追加数据到mg_connection::send_mbuf.他不会再对socket进行任何写操作。真正的IO完 成是在mg_mgr_poll()中检测.一个MG_EV_SEND事件被触发,当IO操作完成。
MG_EV_TIMER:如果调用mg_set_timer()将发送改事件给改连接。
每个连接都有个一个 标志位字段。一些标志位有mongoose改写。例如,如果用户建立了一个外联UDP连接,用udp://1.2.3.4:5678,Mongoose会为这个连接设置MG_F_UDP标志。其他标志只应由用户事件处理程序设置.下面列举了由事件处理程序设置的connection flags的列表:
下面的标志是由Mongoose设置的: