在普通的http請求過程中,ngx_event_accept函數中ls->handler(c);調用了ngx_http_init_connection函數,ngx_http_init_connection函數會調用ngx_http_wait_request_handler。主要代碼和解析如下。
查看事件是否已過期,如果已過期,直接斷開連接
if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_http_close_connection(c); return; }
調用recv函數,接收數據。函數原型在ngx_recv.c中定義,根據是否使用kqueue(一種i/o複用技術),有兩種函數定義。
n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { 尚未有數據道來,由於Nginx的事件驅動機制,程序不會阻塞,註冊讀事件並返回。 if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); return; } 連接有可能什麼實質性工作都不做,所以暫且釋放內存。 if (ngx_pfree(c->pool, b->start) == NGX_OK) { b->start = NULL; } return; }
recv函數返回了錯誤,直接斷開連接並返回。
if (n == NGX_ERROR) { ngx_http_close_connection(c); return; }
client主動斷開了連接。
if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); ngx_http_close_connection(c); return; }
如果有類似於“listen 80 proxy_protocol;”的配置,尚未仔細研究
if (hc->proxy_protocol) { ... } ngx_reusable_connection(c, 0);
調用ngx_http_create_request函數初始化一個ngx_http_request_t結構體。
c->data = ngx_http_create_request(c); if (c->data == NULL) { ngx_http_close_connection(c); return; }
將目標連接的讀事件回調函數設置爲處理處理請求行
rev->handler = ngx_http_process_request_line;
獲取已經有數據到達,所以馬上執行處理請求行函數,在ngx_http_process_request_line中循環調用recv函數,從緩衝區中取東西出來。ngx_thttp_process_request_line函數可能會被調用多次。
ngx_http_process_request_line(rev);