在普通的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);