mongoose之http调试代码
-
使用版本"7.14"
-
交互流程图如下:
-
关键函数
- mg_mgr_init函数
void mg_mgr_init(struct mg_mgr *mgr) {memset(mgr, 0, sizeof(*mgr));
#if MG_ENABLE_EPOLLif ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)MG_ERROR(("epoll_create1 errno %d", errno));
#elsemgr->epoll_fd = -1;
#endif
#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK// clang-format off{ WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }// clang-format on
#elif MG_ENABLE_FREERTOS_TCPmgr->ss = FreeRTOS_CreateSocketSet();
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)// Ignore SIGPIPE signal, so if client cancels the request, it// won't kill the whole process.signal(SIGPIPE, SIG_IGN);
#elif MG_ENABLE_TCPIP_DRIVER_INIT && defined(MG_TCPIP_DRIVER_INIT)MG_TCPIP_DRIVER_INIT(mgr);
#endifmgr->pipe = MG_INVALID_SOCKET;mgr->dnstimeout = 3000;mgr->dns4.url = "udp://8.8.8.8:53";mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";mg_tls_ctx_init(mgr);
}
这是初始化一个mongoose管理结构体,在后面整个程序运行周期中都需要使用。结构体中的struct mg_connection *conns,是链接管理列表,每次有客户端连接都会创建一个id不一样的链接并添加到链接列表中。
- mg_http_listen函数
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,mg_event_handler_t fn, void *fn_data) {struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);if (c != NULL) c->pfn = http_cb;return c;
}struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,mg_event_handler_t fn, void *fn_data) {struct mg_connection *c = NULL;if ((c = mg_alloc_conn(mgr)) == NULL) {MG_ERROR(("OOM %s", url));} else if (!mg_open_listener(c, url)) {MG_ERROR(("Failed: %s, errno %d", url, errno));MG_PROF_FREE(c);free(c);c = NULL;} else {c->is_listening = 1;c->is_udp = strncmp(url, "udp:", 4) == 0;LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);c->fn = fn;c->fn_data = fn_data;mg_call(c, MG_EV_OPEN, NULL);if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection mustMG_DEBUG(("%lu %ld %s", c->id, c->fd, url));}return c;
}
创建一个监听链接,专门用来监听有没有客户端连接。(这里仅仅只是创建一个链接并添加到链接列表中),c->is_listening = 1。并添加了http协议处理回调函数( c->pfn = http_cb)。这个是接收底层数据后,对底层数据进行解析的回调。并且注册了事件处理函数(c->fn = fn)。对http协议解析后进一步进行处理。
- mg_mgr_poll函数
struct mg_connection *c, *tmp;uint64_t now;printf("i----------------------------\r\n");mg_iotest(mgr, ms);now = mg_millis();mg_timer_poll(&mgr->timers, now);for (c = mgr->conns; c != NULL; c = tmp) {printf("++++++++++++is_listening %d,is_udp %d\r\n",c->is_listening,c->is_udp);bool is_resp = c->is_resp;tmp = c->next;mg_call(c, MG_EV_POLL, &now);if (is_resp && !c->is_resp) {printf("====================possible?\r\n");long n = 0;mg_call(c, MG_EV_READ, &n);}MG_VERBOSE(("%lu %c%c %c%c%c%c%c %lu %lu", c->id,c->is_readable ? 'r' : '-', c->is_writable ? 'w' : '-',c->is_tls ? 'T' : 't', c->is_connecting ? 'C' : 'c',c->is_tls_hs ? 'H' : 'h', c->is_resolving ? 'R' : 'r',c->is_closing ? 'C' : 'c', mg_tls_pending(c), c->rtls.len));if (c->is_resolving || c->is_closing) {// Do nothing} else if (c->is_listening && c->is_udp == 0) {if (c->is_readable) accept_conn(mgr, c);} else if (c->is_connecting) {if (c->is_readable || c->is_writable) connect_conn(c);//} else if (c->is_tls_hs) {// if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);} else {if (c->is_readable) read_conn(c);if (c->is_writable) write_conn(c);}if (c->is_draining && c->send.len == 0) c->is_closing = 1;if (c->is_closing) close_conn(c);}
}
- mg_iotest: 会去监听每个链接,查看链接是否有读的数据,写的数据,或者新的链接。c->is_readable/c->is_writable主要设置这两个变量。
- mg_timer_poll: 轮询处理定时器任务处理。
- mg_call(c, MG_EV_POLL, &now): 这个用的很妙,比如在发送比较大的文件时,会去调用如static_cb回调函数。每次轮询到此位置时,都会去进入到static_cb函数中,然后填充c->send缓冲区。
- mg_call(c, MG_EV_READ, &n): 这个是在数据处理完时,会去读有没有新的http请求进来。如果有继续处理?
- write_conn: 发送数据。