本章将继续介绍HTTP模块初始化函数:ngx_http_block中的内容。将会涉及到server块的组织,监听端口的管理,以及ip地址和server块之间的组织关系。下面我们将从listen关键字说起,然后根据listen配置项以及它的解析函数了解nginx组织server块和监听端口的过程。最后在介绍ngx_http_optimize_servers函数。所有这些工作都是为了实现Nginx的虚拟主机功能。看看nginx是怎么样使得每个请求可以迅速根据它的host,Ip匹配到它对应的虚拟主机server块的。
listen配置项在ngx_http_core_module中:
{ ngx_string("listen"),
NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
ngx_http_core_listen,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
因此可以看到,它只能存在与server块中。它可以包含读个参数,具体地:
listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000;
主要是以listen [addr:] port的格式。
除此之外,他还可以有以下的格式:
listen 127.0.0.1 default_server accept_filter=dataready backlog=1024;
这个主要是对监听端口的属性的设置参数。
listen的配置指令函数是:
static char *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
也就是,当conf_parse函数解析完listen指令之后,就会调用这个函数处理这个指令以及指令对应的参数,其中,指令参数存储在
cf->args->elts
中。下面我们来解析ngx_http_core_listen函数。
首先调用ngx_parse_url函数解析listen的第一个参数,主要是为了解析出addr:port。
u.url = value[1];
u.listen = 1;
u.default_port = 80;
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
....
这个函数执行结束,一般会初始化完成u。
然后nginx会根据listen的其他参数(除addr,port)和前面初始化过的u来初始化:
ngx_http_listen_opt_t lsopt;
这部分主要是在下面的一个大for循环中完成:
ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen);
lsopt.socklen = u.socklen