ngx_http_init_listening

张开发
2026/4/6 19:56:18 15 分钟阅读

分享文章

ngx_http_init_listening
1 定义ngx_http_init_listening 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_init_listening(ngx_conf_t*cf,ngx_http_conf_port_t*port){ngx_uint_ti,last,bind_wildcard;ngx_listening_t*ls;ngx_http_port_t*hport;ngx_http_conf_addr_t*addr;addrport-addrs.elts;lastport-addrs.nelts;/* * If there is a binding to an *:port then we need to bind() to * the *:port only and ignore other implicit bindings. The bindings * have been already sorted: explicit bindings are on the start, then * implicit bindings go, and wildcard binding is in the end. */if(addr[last-1].opt.wildcard){addr[last-1].opt.bind1;bind_wildcard1;}else{bind_wildcard0;}i0;while(ilast){if(bind_wildcard!addr[i].opt.bind){i;continue;}lsngx_http_add_listening(cf,addr[i]);if(lsNULL){returnNGX_ERROR;}hportngx_pcalloc(cf-pool,sizeof(ngx_http_port_t));if(hportNULL){returnNGX_ERROR;}ls-servershport;hport-naddrsi1;switch(ls-sockaddr-sa_family){#if(NGX_HAVE_INET6)caseAF_INET6:if(ngx_http_add_addrs6(cf,hport,addr)!NGX_OK){returnNGX_ERROR;}break;#endifdefault:/* AF_INET */if(ngx_http_add_addrs(cf,hport,addr)!NGX_OK){returnNGX_ERROR;}break;}addr;last--;}returnNGX_OK;}ngx_http_init_listening 函数用于 将监听配置转为 ngx_listening_t 监听结构体来统一管理详解1 函数签名staticngx_int_tngx_http_init_listening(ngx_conf_t*cf,ngx_http_conf_port_t*port)返回值 NGX_OK 0表示函数执行成功。 NGX_ERROR -1表示发生错误参数 ngx_conf_t *cf 指向配置解析上下文 ngx_http_conf_port_t *port ngx_http_conf_port_t 是 HTTP 模块中表示一个监听端口的配置结构体 是本次要处理的输入数据2 逻辑流程1 局部变量 2 判断是否存在通配地址 3 遍历地址数组 4 返回成功1 局部变量{ngx_uint_ti,last,bind_wildcard;ngx_listening_t*ls;ngx_http_port_t*hport;ngx_http_conf_addr_t*addr;2 判断是否存在通配地址addrport-addrs.elts;lastport-addrs.nelts;#1 将 port 结构体中的 addrs 数组的 elts 指针赋值给局部变量 addr addrs动态数组管理着该端口上所有要监听的地址配置 #2 将 port 结构体中的 addrs 数组的当前元素个数赋值给局部变量 last/* * If there is a binding to an *:port then we need to bind() to * the *:port only and ignore other implicit bindings. The bindings * have been already sorted: explicit bindings are on the start, then * implicit bindings go, and wildcard binding is in the end. */if(addr[last-1].opt.wildcard){addr[last-1].opt.bind1;bind_wildcard1;}else{bind_wildcard0;}#1 检查地址数组的最后一个元素索引 last - 1是否标记为通配符地址。 .opt.wildcard 是 ngx_http_conf_addr_t 结构体中的 opt 字段类型为 ngx_http_listen_opt_t的成员 wildcard 是一个标志位。若为 1 表示该地址是通配地址 *:port。 通配地址 被排序在最后 因此只需检查最后一个元素是否为通配符即可判断是否存在通配绑定。 #2 将最后一个地址通配地址的 bind 标志设置为 1 表示需要实际创建监听套接字并绑定该地址。 .opt.bind 是 ngx_http_listen_opt_t 中的另一个标志位 指示是否应当对该地址执行 bind() 系统调用。 默认情况下隐式绑定的地址可能 bind 0 而显式绑定或通配地址需要 bind 1 #3 将局部变量 bind_wildcard 设置为 1 标记“存在通配绑定且需要特殊处理”模式 当存在通配地址时只创建通配地址的监听套接字忽略其他隐式地址 #4 将 bind_wildcard 设置为 0 表示“不存在通配绑定正常处理所有地址”3 遍历地址数组i0;初始化循环索引为0 i 作为循环索引用于遍历地址数组while(ilast){开始循环条件为当前索引 i 小于剩余地址数量 last last 初始为地址总数但在循环内部会通过 last-- 递减 同时 addr 指针递增if(bind_wildcard!addr[i].opt.bind){i;continue;}#1 检查是否处于“通配绑定模式”且当前地址的 bind 标志为假0。 bind_wildcard 在前面的代码中已设置存在通配地址时为 1否则为 0。 addr[i].opt.bind 是地址配置中的 bind 字段表示该地址是否需要实际创建监听套接字。 当存在通配地址时只处理 bind 1 的地址通配地址本身已被强制设为 1 而跳过 bind 0 的隐式绑定地址。 #2 将索引 i 加 1lsngx_http_add_listening(cf,addr[i]);if(lsNULL){returnNGX_ERROR;}为当前地址创建监听管理结构体 返回对应的 ngx_listening_t 结构体指针hportngx_pcalloc(cf-pool,sizeof(ngx_http_port_t));if(hportNULL){returnNGX_ERROR;}ls-servershport;分配内存 将新分配的 hport 赋值给监听结构体的 servers 字段ls-servers 其作用是让底层的监听对象能够关联到上层配置hport-naddrsi1;设置 hport 中的地址数量为 i 1在循环中i 的初始值为 0且只有当跳过不需要绑定的地址时才会 i。 当处理到需要绑定的地址时i 的值等于之前跳过的地址个数 实际效果 在非通配模式下bind_wildcard 0i 始终为 0 所以 hport-naddrs 1表示每个监听套接字只关联一个地址。 在通配模式下i 1 记录关联地址配置的数量 i 是跳过的隐式地址数量 1 代表最后一个通配地址 所以 hport-naddrs 表示的是当前 当前监听管理结构体 ls 关联的配置地址数量switch(ls-sockaddr-sa_family){#if(NGX_HAVE_INET6)caseAF_INET6:if(ngx_http_add_addrs6(cf,hport,addr)!NGX_OK){returnNGX_ERROR;}break;#endifdefault:/* AF_INET */if(ngx_http_add_addrs(cf,hport,addr)!NGX_OK){returnNGX_ERROR;}break;}addr;last--;}#1 根据监听套接字地址结构中的协议族sa_family进行多分支选择#2 当监听地址是 IPv6 类型时 调用 ngx_http_add_addrs6 函数 将 IPv6 地址配置信息添加到 hport 结构中 cf配置上下文提供内存池、日志等。 hport当前 HTTP 端口结构体用于存储地址列表。 addr当前指向 ngx_http_conf_addr_t 数组位置的指针#3 默认处理 IPv4 调用 ngx_http_add_addrs 函数IPv4 版本 将地址配置信息添加到 hport#4 将地址指针 addr 向后移动一个元素 即指向数组中的下一个地址 将剩余地址计数 last 减 1 因为 addr 已经前移剩余的有效地址数量减少一个4 返回成功returnNGX_OK;}3 总结ngx_http_init_listening 函数用于 将监听配置转为 ngx_listening_t 监听结构体来统一管理 当存在 通配地址时通配地址可以和其他 隐式地址(bind0) 共用一个监听对象 于是先排序 按 显示隐式通配的顺序排序 前面的显示地址每个地址创建一个监听结构体来管理 后面的 隐式通配 地址由于底层可以共用一个监听对象 所以 只需为它们创建一个监听结构体来管理 这一个 监听结构体 就关联了多个 监听配置 hport 中就记录了 这一个监听结构体到底 关联了多少个 监听配置 (hport-naddrs) 以及关联的是哪些 监听配置(hport-addrs)

更多文章