上一篇文章我们分析了位置指令的解析过程,简单的回顾一下这个内容:每个位置对应一个ngx_http_core_loc_conf_t结构体,所有的位置通过一个双向队列连接在一起。数据结构比较复杂。
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解。与网络有关的配置命令主要有两个:听和sever_name.listen命令设置nginx监听地址,对于IP协议,这个地址就是地址和端口,对于UNIX域套接字协议,这个地址就是路径,一条听指令只能指定一个地址或者港口,地址也可以是主机名
从这一篇文章开始,我们分析指听令的解析过程,指听令的配置如下:从nginx.org的手册中我们可以获取听的使用方法:
听地址[:端口][default_server] [setfib=数量][积压数量=][rcvbuf=大小][sndbuf=大小][accept_filter=过滤](延期)(绑定)[ipv6only=|关闭](ssl) [so_keepalive=|关闭| [keepidle]: [keepintvl]: [keepcnt]],
一个听指令携带的参数是很复杂的。不过,我们一般很少关注那些不太常用的参数,以下是一些常用的配置方式:
听127.0.0.1:8000; 听127.0.0.1不加端口,默认监听80端口; 听8000 听*:8000 听localhost: 8000
解析听指令中的uri和端口
从上面的内容知道,听着有多种用法,我们在解析的时候需要获取到指听令的端口号和uri部分,nginx提供了ngx_parse_url()方法来解析uri和端口,该函数在解析指听令的时候会被调用。
ngx_int_t ngx_parse_url (ngx_pool_t *池,ngx_url_t * u) { u_char * p; size_t len; p=u→url.data; len=u→url.len;//这里是解析unix域的协议 如果(len祝辞=5,,ngx_strncasecmp (p (u_char *)unix:“5)==0) { 返回ngx_parse_unix_domain_url(池,u); }//解析IPV6协议 如果(len,,p [0]==() { 返回ngx_parse_inet6_url(池,u); }//解析IPV4协议 返回ngx_parse_inet_url(池,u); }
我们使用的是IPV4协议,这里分析ngx_parse_inet_url()函数
//u。url=" 80 ";//u。听=1;//u.default_port=80; 静态ngx_int_t ngx_parse_inet_url (ngx_pool_t *池,ngx_url_t * u) { u_char * p, *, *端口,*,* uri, * args; size_t len; ngx_int_t n; 结构指向sockaddr_in *罪; #如果(NGX_HAVE_INET6) struct sockaddr_in6 * sin6; # endif u→socklen=sizeof (struct指向sockaddr_in); 罪=(struct指向sockaddr_in *)和u→sockaddr; 罪恶→sin_family=AF_INET;//IPV4类型 u→家庭=AF_INET; 主机=u→url.data;//?0” 去年=主机+ u→url.len;//主机的最后字符的位置 端口=ngx_strlchr(主机,最后,“:”);//找到港口,这里为NULL uri=ngx_strlchr(主机、最后'/');//找到uri,这里为NULL args=ngx_strlchr(主机,最后,“& # 63;”);//找到参数参数,这里为NULL 如果(args) { 如果(uri==NULL | | args & lt;uri) { uri=参数; } } 如果(uri) { 如果(u→听| | ! u→uri_part) { u→呃=拔扌У闹骰? 返回NGX_ERROR; } u→uri。len=去年- uri; u→uri。数据=https://www.yisu.com/zixun/uri; 去年=uri; 如果(uri <端口){ 端口=零; } } 如果(端口){ 港口+ +; len=去年-端口; n=ngx_atoi(港口,len); 如果(n <1 | | n> 65535) { u ->呃=拔扌Ф丝凇? 返回NGX_ERROR; } u→端口=(in_port_t) n; 罪恶→sin_port=htons (n) (in_port_t); u→port_text。len=兰; u→port_text。数据=https://www.yisu.com/zixun/port; 去年=港口- 1; 其他}{ 如果(uri==NULL) { 如果(u ->听){/*测试值作为端口> { ngx_string(“倾听”), NGX_HTTP_SRV_CONF | NGX_CONF_1MORE, ngx_http_core_listen, NGX_HTTP_SRV_CONF_OFFSET, 0, 零 }
从配置文件中我们可以知道,只听能出现在服务器模块中,可以带有多个参数。
对应的处理函数为ngx_http_core_listen、下面我们分析这个函数,我们删除了一些进行错误判断的代码,
静态char * ngx_http_core_listen (ngx_conf_t * cf, ngx_command_t * cmd, void *配置) { ngx_http_core_srv_conf_t *产销=相依; ngx_str_t *值,大小; ngx_url_t u; ngx_uint_t n; ngx_http_listen_opt_t lsopt; 论述→听=1; 值=https://www.yisu.com/zixun/cf->参数->英语教学; ngx_memzero (u, sizeof (ngx_url_t)); u。url=价值[1]; u。听=1; u.default_port=80; 如果(ngx_parse_url (cf ->池,u) !=NGX_OK) { 返回NGX_CONF_ERROR; } ngx_memzero (&lsopt sizeof (ngx_http_listen_opt_t)); ngx_memcpy (&lsopt.sockaddr。sockaddr, u。sockaddr u.socklen); lsopt。socklen=u.socklen; lsopt。积压=NGX_LISTEN_BACKLOG; lsopt。rcvbuf=1; lsopt。sndbuf=1; #如果(NGX_HAVE_SETFIB) lsopt。setfib=1; # endif #如果(NGX_HAVE_TCP_FASTOPEN) lsopt。fastopen=1; # endif lsopt。通配符=u.wildcard; #如果(NGX_HAVE_INET6) lsopt。ipv6only=1; # endif (空白)ngx_sock_ntop (&lsopt.sockaddr。sockaddr lsopt。socklen lsopt.addr, NGX_SOCKADDR_STRLEN, 1); (n=2;nnginx中的听指令实例解析