与网络有关的配置命令主要有两个:listen和sever_name。首先先了解这两个命令的用法。
listen命令设置nginx监听地址,nginx从这里接受请求。对于IP协议,这个地址就是address和port;对于UNIX域套接字协议,这个地址就是path。 一条listen指令只能指定一个address或者port。 address也可以是主机名。 比如:
1 listen 127.0.0.1:8000;
2 listen 127.0.0.1;
3 listen 8000;
4 listen *:8000;
5 listen localhost:8000;
UNIX域套接字则使用“unix:”前缀:
可以为listen指令定义若干额外的参数,这些参数用于套接字相关的系统调用。 这些参数可以在任何listen指令中指定,但是对于每个address:port,只能定义一次。具体参数看以到nginx帮助文档中查到,这里就不再说明了。
listen指令描述虚拟主机接受连接的地址和端口,用server_name指令列出虚拟主机的所有主机名。
第一个名字成为虚拟主机的首要主机名。
1 server { 2 server_name example.com *.example.com www.example.*; 3 }
更详细的介绍:http://nginx.org/cn/docs/http/server_names.html
ngx_http_add_listen中调用了ngx_http_add_addresses和ngx_http_add_address函数,先看下ngx_http_add_addresses:
这个函数代码很简单,初始化地址列表,并调用ngx_http_add_server将新的虚拟主机的配置加入到address:port对应的虚拟主机列表中。下面再看下ngx_http_add_server函数:
1 static ngx_int_t
2 ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
3 ngx_http_conf_addr_t *addr)
4 {
5 ...
6 server = ngx_array_push(&addr->servers); //添加新的虚拟主机配置
7 if (server == NULL) {
8 return NGX_ERROR;
9 }
10 *server = cscf;
11 return NGX_OK;
12 }
这个函数主要是把server_name命令后面各个主机名放到当前虚拟主机配置的server_names数组中。
上面代码主要就是将每个address:port对应的所有域名与域名所在的虚拟主机配置信息建立hash映射,这样就可以通过域名快速找到域名所在的虚拟主机配置信息。有关nginx的hash可以参考 nginx源码分析之hash的实现 这篇文章。下面再看下ngx_http_init_listening函数:
1 static ngx_int_t
2 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
3 {
4 ...
5 addr = port->addrs.elts;
6 last = port->addrs.nelts;
7 if (addr[last - 1].opt.wildcard) {
8 addr[last - 1].opt.bind = 1;
9 bind_wildcard = 1;
10
11 } else {
12 bind_wildcard = 0;
13 }
14 i = 0;
15 while (i < last) { //last代表的是address:port的个数
16 //忽略隐式绑定
17 if (bind_wildcard && !addr[i].opt.bind) {
18 i++;
19 continue;
20 }
21 //这个函数里面将会创建,并且初始化listen结构,这个listen已经存放在cycle结构的listen数组中
22 ls = ngx_http_add_listening(cf, &addr[i]);
23 if (ls == NULL) {
24 return NGX_ERROR;
25 }
26 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
27 ...
28 ls->servers = hport;
29 if (i == last - 1) { //将*:port和没有显式bind的address:port放在同一个listen中
30 hport->naddrs = last;
31 } else {
32 hport->naddrs = 1;
33 i = 0; //i重新赋值为0
34 }
35 switch (ls->sockaddr->sa_family) {
36 ...
37 default: /* AF_INET */
38 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { //初始化虚拟主机相关的地址,设置hash等等.
39 return NGX_ERROR;
40 }
41 break;
42 }
43 addr++;
44 last--;
45 }
46 return NGX_OK;
47 }
建立监听套接字是在ngx_open_listening_sockets中完成,这个函数是在ngx_init_cycle中被调用的。