Mongoose6.0源码分析(1)-从一个example开始到读取数据

来源:互联网 发布:mac finder 侧边栏 编辑:程序博客网 时间:2024/04/30 07:06

/*摘自pi9nc博客http://blog.csdn.net/pi9nc/article/details/23129377

Mongoose是一种WEB服务器,因为最近在学习网络编程,所以打算研究研究它的源码,认真看了大部分,觉得学到的东西的确不少,拿出来分享一下,也和大家交流交流

至于什么是WEB服务器,以及Mongoose作为一种轻量级的WEB服务器,它有哪些优点,这里给个链接:http://www.cnblogs.com/skynet/archive/2010/07/24/1784322.html

刚开始,也是看作者的文章才产生兴趣读源码,所以分享很重要(^o^)

*/

pignc也是读了吴秦(Tyler)的文章所以开始阅读Mongoose源码。我下载了Mongoose6.0的源码,我发现结构已经完全变了,包括数据结构的定义。能找到的只剩下struct mg_connection,但也变得面目全非了。作为新手我想学习中不断记录着。

请参考pi9nc的文章,我也从一个 example开始吧

#include "mongoose.h"static const char *s_http_port = "8000";static struct mg_serve_http_opts s_http_server_opts;static void ev_handler(struct mg_connection *nc, int ev, void *p) {  if (ev == MG_EV_HTTP_REQUEST) {    mg_serve_http(nc, p, s_http_server_opts);  }}int main(void) {  struct mg_mgr mgr;  struct mg_connection *nc;  mg_mgr_init(&mgr, NULL);  nc = mg_bind(&mgr, s_http_port, ev_handler);  // Set up HTTP server parameters  mg_set_protocol_http_websocket(nc);  s_http_server_opts.document_root = ".";  // Serve current directory  s_http_server_opts.enable_directory_listing = "yes";  printf("Starting web server on port %s\n", s_http_port);  for (;;) {    mg_mgr_poll(&mgr, 1000);  }  mg_mgr_free(&mgr);  return 0;}

以上代码实现了一个简单的web服务,重点几个结构和函数如下:
struct mg_mgr 
。。。。
struct mg_connection
。。。。
mg_mgr_init  (mg_create_server 5.2,包含了bind用函数mg_socketpair 更早 mg_start)
对windows来说实际执行的就两句(个人理解,不一定准确),定义使用select,linux是epoll
WSADATA data;
 WSAStartup(MAKEWORD(2, 2), &data);//初始化Winsock 2.2

mg_start_thread 可以循环使用此函数实现多线程

  1. void* process_proc(void* p_server)  
  2. {  
  3.     while(!stop_webserver)  
  4.     {  
  5.         mg_poll_server((struct mg_server*)p_server, 500);  
  6.     }  
  7.     return NULL;  
  8. }  
  9.   
  10. bool start_simple_webserver(void) {  
  11.     stop_webserver = false;  
  12.     for(int i = 0; i < MAX_THREADS; i++)  
  13.     {  
  14.         server[i] = mg_create_server(NULL);  
  15.         if(i == 0)  
  16.         {  
  17.             mg_set_option(server[i], "listening_port", port);  
  18.         }  
  19.         else  
  20.         {  
  21.             mg_set_listening_socket(server[i], mg_get_listening_socket(server[0]));  
  22.         }  
  23.         mg_set_option(server[i], "document_root", local_fullpath);  
  24.         mg_set_request_handler(server[i], request_handler);  
  25.         mg_start_thread(process_proc, server[i]);  
  26.     }  
  27.   

mg_bind(实际是mg_bind_opt函数完成的  (5.2mg_socketpair))

执行了Mongoose中三个函数,返回连接句柄nc
1. mg_parse_address
对socket_address *sa进行一系列配置 ,即域名或IP,端口进行了配置,此例中只用到端口号
2. mg_open_listening_socket
实现了套接字的socket、bind、listen
另,SOCK_STREAM tcp; SOCK_DGRAM udp. 
        端口重用SO_REUSEADDR 和端口独占 SO_EXCLUSIVEADDRUSE
3.mg_add_sock_opt

  包含两个函数

 mg_create_connection 将各种连接配置信息写入struct mg_connection中,回调函数句柄在conn(nc)->handler

mg_set_sock 增加新连接进入连接的链表,链表好像是倒置的,后加入的通过mgr->active_connections指针先读到

定了nc-〉handler=用户给定的  static void ev_handler 函数指针。

mg_set_protocol_http_websocket(nc);

指定nc->proto_handle=http_handler

mg_mgr_poll(5.2mg_poll_server)
mg_add_to_set 设置socket功能:读、写、err

select()库函数  ,由于Mongoose需要兼容linux,因此使用select I/O模型。最近去看完成端口模型了,因此Mongoose源码分析放下了。

mg_mgr_handle_connection(5.2 accept_new_connection,老吴提到老版本get_socket())处理读(mg_read_from_socket)、写(mg_write_to_socket)、accept(accept_conn)、eer

使用nc-〉flags来区分socket状态,很有参考价值

mg_read_from_socket 读取函数(5.2read_from_socket)


while ((n = (int) MG_EV_RECV_FUNC(
                conn->sock, buf, recv_avail_size(conn, sizeof(buf)), 0)) > 0) { //read(s, b, l) 返回读取的字节数 如果0表示读取结束

直到返回为0,表示完全读取,跳my_call(5.2process_request)函数进行处理

处理了ssl加密的情况。

my_call 重要的函数

回调http包处理函数http_handle对http包进行处理。语句ev_handler(nc, ev, ev_data);//用到了http_handle//运行http_handle(5.2open_local_endpoint)

(回调指针传的很隐蔽,眼都看花了)


 mg_mgr_free
。。。。。。
因为此例是做一个简单的web服务器,因此在开始时定义mg_serve_http_opts的对象设置服务器基本属性


<span style="font-family: Arial, Helvetica, sans-serif;">struct mg_serve_http_opts {</span>
   const char *per_directory_auth_file;   const char *auth_domain;   const char *global_auth_file;    const char *enable_directory_listing;  const char *ssi_pattern;  const char *ip_acl;   const char *url_rewrites;   const char *dav_document_root;   const char *hidden_file_pattern;   const char *cgi_file_pattern;    const char *cgi_interpreter;    const char *custom_mime_types;};


MG_MAX_HOST_LEN 200  最大链接数200


定义了如下一些宏来进行区分处理

#define MG_EV_POLL 0    /* Sent to each connection on each mg_mgr_poll() call */
#define MG_EV_ACCEPT 1  /* New connection accepted. union socket_address * */
#define MG_EV_CONNECT 2 /* connect() succeeded or failed. int *  */
#define MG_EV_RECV 3    /* Data has benn received. int *num_bytes */
#define MG_EV_SEND 4    /* Data has been written to a socket. int *num_bytes */
#define MG_EV_CLOSE 5   /* Connection is closed. NULL */


0 0
原创粉丝点击