ngx_http_add_addrs

张开发
2026/4/13 7:44:07 15 分钟阅读

分享文章

ngx_http_add_addrs
1 定义ngx_http_add_addrs 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_add_addrs(ngx_conf_t*cf,ngx_http_port_t*hport,ngx_http_conf_addr_t*addr){ngx_uint_ti;ngx_http_in_addr_t*addrs;structsockaddr_in*sin;ngx_http_virtual_names_t*vn;hport-addrsngx_pcalloc(cf-pool,hport-naddrs*sizeof(ngx_http_in_addr_t));if(hport-addrsNULL){returnNGX_ERROR;}addrshport-addrs;for(i0;ihport-naddrs;i){sin(structsockaddr_in*)addr[i].opt.sockaddr;addrs[i].addrsin-sin_addr.s_addr;addrs[i].conf.default_serveraddr[i].default_server;#if(NGX_HTTP_SSL)addrs[i].conf.ssladdr[i].opt.ssl;#endif#if(NGX_HTTP_V2)addrs[i].conf.http2addr[i].opt.http2;#endifaddrs[i].conf.proxy_protocoladdr[i].opt.proxy_protocol;if(addr[i].hash.bucketsNULL(addr[i].wc_headNULL||addr[i].wc_head-hash.bucketsNULL)(addr[i].wc_tailNULL||addr[i].wc_tail-hash.bucketsNULL)#if(NGX_PCRE)addr[i].nregex0#endif){continue;}vnngx_palloc(cf-pool,sizeof(ngx_http_virtual_names_t));if(vnNULL){returnNGX_ERROR;}addrs[i].conf.virtual_namesvn;vn-names.hashaddr[i].hash;vn-names.wc_headaddr[i].wc_head;vn-names.wc_tailaddr[i].wc_tail;#if(NGX_PCRE)vn-nregexaddr[i].nregex;vn-regexaddr[i].regex;#endif}returnNGX_OK;}ngx_http_add_addrs 函数的作用是 将解析得到的 IPv4 地址配置转换为端口结构内部使用的地址数组 以便 Nginx 在运行时能够根据每个 IPv4 地址独立处理连接和虚拟主机匹配。2 详解1 函数签名staticngx_int_tngx_http_add_addrs(ngx_conf_t*cf,ngx_http_port_t*hport,ngx_http_conf_addr_t*addr)返回值 NGX_OK (0)成功。 NGX_ERROR (-1)失败参数 ngx_conf_t *cf 指向配置解析上下文 ngx_http_port_t *hport 代表一个 监听端口 的抽象结构 该结构包含了该端口上所有地址的配置信息、监听套接字、连接处理函数等 该参数是函数的 输出目标即函数将转换后的地址配置存储到 hport 中 ngx_http_conf_addr_t *addr 指向一个 配置地址数组 的起始位置。 每个元素代表一个具体的 IPv4 地址 是本次要处理的输入数据2 逻辑流程1 局部变量 2 分配内存 3 循环遍历处理每个输入的地址配置 4 返回成功1 局部变量{ngx_uint_ti;ngx_http_in_addr_t*addrs;structsockaddr_in*sin;ngx_http_virtual_names_t*vn;2 分配内存hport-addrsngx_pcalloc(cf-pool,hport-naddrs*sizeof(ngx_http_in_addr_t));if(hport-addrsNULL){returnNGX_ERROR;}为 hport 分配一块连续的内存 用于存放该端口上所有 地址的配置信息。 清零初始化 使用 ngx_pcalloc 分配的同时将内存全部清零 确保未显式赋值的字段具有安全的初始值0 或 NULL。 错误处理 若分配失败函数立即返回 NGX_ERROR终止当前配置处理流程。3 循环遍历处理每个输入的地址配置addrshport-addrs;for(i0;ihport-naddrs;i){sin(structsockaddr_in*)addr[i].opt.sockaddr;addrs[i].addrsin-sin_addr.s_addr;addrs[i].conf.default_serveraddr[i].default_server;#if(NGX_HTTP_SSL)addrs[i].conf.ssladdr[i].opt.ssl;#endif#if(NGX_HTTP_V2)addrs[i].conf.http2addr[i].opt.http2;#endifaddrs[i].conf.proxy_protocoladdr[i].opt.proxy_protocol;if(addr[i].hash.bucketsNULL(addr[i].wc_headNULL||addr[i].wc_head-hash.bucketsNULL)(addr[i].wc_tailNULL||addr[i].wc_tail-hash.bucketsNULL)#if(NGX_PCRE)addr[i].nregex0#endif){continue;}vnngx_palloc(cf-pool,sizeof(ngx_http_virtual_names_t));if(vnNULL){returnNGX_ERROR;}addrs[i].conf.virtual_namesvn;vn-names.hashaddr[i].hash;vn-names.wc_headaddr[i].wc_head;vn-names.wc_tailaddr[i].wc_tail;#if(NGX_PCRE)vn-nregexaddr[i].nregex;vn-regexaddr[i].regex;#endif}#1 将局部指针 addrs 指向刚刚分配好的 hport-addrs 内存区域#2 循环遍历每个地址配置 循环次数 hport-naddrs 是该端口上需要绑定的 地址总数 每次循环处理一个地址addr[i] 是输入配置 addrs[i] 是输出结果#3 获取 地址并复制#4 复制基础配置标志#5 如果该地址没有任何虚拟主机名配置包括精确匹配、通配符前缀、通配符后缀、正则表达式 则不需要分配 virtual_names 结构直接跳过后续代码continue 此时 addrs[i].conf.virtual_names 保持为 NULL。 条件拆解 addr[i].hash.buckets NULL 精确匹配的哈希表ngx_hash_t未初始化没有 server_name 精确匹配项。 addr[i].wc_head NULL 或者没有前缀通配符结构如 *.example.com。 如果 wc_head 非空还需要检查其内部的 hash.buckets 是否为 NULL即虽然创建了结构但实际没有条目。 addr[i].wc_tail NULL 同理后缀通配符如 www.*为空或没有实际条目。 #if (NGX_PCRE) 如果支持正则表达式则要求 addr[i].nregex 0即没有正则匹配的 server_name。 逻辑意义 性能优化 大多数简单的 server 块可能只监听一个 IP 端口 没有复杂的虚拟主机名或者只有默认服务器。 此时不需要分配额外的 virtual_names 结构节省内存。 当客户端连接到达时如果 virtual_names 为 NULL Nginx 会直接使用该地址的默认服务器或仅有的服务器配置。4 返回成功returnNGX_OK;}

更多文章