ngx_http_add_listen

声明在 src\http\ngx_http.h

复制代码
ngx_int_t ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
    ngx_http_listen_opt_t *lsopt);

定义在 src\http\ngx_http.c

复制代码
ngx_int_t
ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
    ngx_http_listen_opt_t *lsopt)
{
    in_port_t                   p;
    ngx_uint_t                  i;
    struct sockaddr            *sa;
    ngx_http_conf_port_t       *port;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

    if (cmcf->ports == NULL) {
        cmcf->ports = ngx_array_create(cf->temp_pool, 2,
                                       sizeof(ngx_http_conf_port_t));
        if (cmcf->ports == NULL) {
            return NGX_ERROR;
        }
    }

    sa = lsopt->sockaddr;
    p = ngx_inet_get_port(sa);

    port = cmcf->ports->elts;
    for (i = 0; i < cmcf->ports->nelts; i++) {

        if (p != port[i].port || sa->sa_family != port[i].family) {
            continue;
        }

        /* a port is already in the port list */

        return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
    }

    /* add a port to the port list */

    port = ngx_array_push(cmcf->ports);
    if (port == NULL) {
        return NGX_ERROR;
    }

    port->family = sa->sa_family;
    port->port = p;
    port->addrs.elts = NULL;

    return ngx_http_add_address(cf, cscf, port, lsopt);
}

这个函数是Nginx在解析配置时用于添加监听端口的核心逻辑


函数签名

返回值:ngx_int_t

  • NGX_OK(0):成功添加监听配置。
  • NGX_ERROR(-1):内存分配失败或地址冲突等错误

参数

ngx_conf_t *cf
  • 类型 :指向 ngx_conf_t 结构体的指针。
  • 作用
    表示 Nginx 配置解析的上下文(Context),包含当前解析的配置文件路径、内存池(temp_pool)、日志对象等关键信息

ngx_http_core_srv_conf_t *cscf
  • 类型 :指向 ngx_http_core_srv_conf_t 结构体的指针。
  • 作用
    表示当前正在配置的 HTTP server 块的核心配置。每个 server 块在 Nginx 中对应一个虚拟主机,该结构体存储了与该虚拟主机相关的配置信息。

ngx_http_listen_opt_t *lsopt
  • 类型 :指向 ngx_http_listen_opt_t 结构体的指针。
  • 作用
    封装了从配置文件中解析出的 listen 指令参数。例如,用户配置 listen 80;listen 443 ssl; 时,参数会被解析到该结构体中。

复制代码
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

获取 HTTP 核心模块的主配置结构体

定义在

src\http\ngx_http_config.h

复制代码
#define ngx_http_conf_get_module_main_conf(cf, module)                        \
    ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
复制代码
    if (cmcf->ports == NULL) {
        cmcf->ports = ngx_array_create(cf->temp_pool, 2,
                                       sizeof(ngx_http_conf_port_t));
        if (cmcf->ports == NULL) {
            return NGX_ERROR;
        }
    }

cmcf->portsngx_http_core_main_conf_t 结构体中的一个动态数组(ngx_array_t),用于存储所有监听端口的配置

如果 portsNULL,表示这是首次添加监听端口,需要初始化数组

  • cf->temp_pool :内存池(ngx_pool_t),用于分配数组内存。配置阶段的临时内存池(temp_pool)会在配置解析完成后被释放或重置。
  • 2:数组的初始容量(预分配 2 个元素的空间),减少后续扩容的次数。
  • sizeof(ngx_http_conf_port_t):数组元素的大小,每个元素对应一个监听端口的配置。

ngx_http_core_main_conf_t-CSDN博客

复制代码
    sa = lsopt->sockaddr;

获取监听配置中的套接字地址结构

复制代码
    p = ngx_inet_get_port(sa);

从套接字地址结构中提取端口号,并将其转换为主机字节序(Host Byte Order),以便后续逻辑处理

复制代码
    port = cmcf->ports->elts;
    for (i = 0; i < cmcf->ports->nelts; i++) {

        if (p != port[i].port || sa->sa_family != port[i].family) {
            continue;
        }

        /* a port is already in the port list */

        return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
    }

遍历已存在的端口列表

若端口号或协议族不匹配,跳过当前端口,继续检查下一个

匹配成功

ngx_http_add_addresses :将当前监听地址(lsopt)添加到已存在的端口配置(port[i])的地址列表中

  • 合并同一端口的多个监听配置,避免重复绑定(例如多个 server 块监听 80 端口的不同 IP 地址)。
  • 减少 bind() 系统调用次数,提升性能。

此时 ports->nelts=0

复制代码
    /* add a port to the port list */

    port = ngx_array_push(cmcf->ports);
    if (port == NULL) {
        return NGX_ERROR;
    }

    port->family = sa->sa_family;
    port->port = p;
    port->addrs.elts = NULL;

添加一个新元素到数组中

ngx_http_conf_port_t-CSDN博客

复制代码
return ngx_http_add_address(cf, cscf, port, lsopt);

将新的监听地址(lsopt)添加到指定端口(port)的地址列表中

ngx_http_add_address-CSDN博客

相关推荐
左手厨刀右手茼蒿1 小时前
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构
网络·flutter·http
江南风月1 小时前
日志审计系统WGLOG支持syslog吗
运维·网络·日志审计
Blurpath住宅代理2 小时前
代理IP全面解析:从协议原理到高阶应用场景的技术指南
网络·静态ip·动态代理·住宅ip·住宅代理
晏宁科技YaningAI3 小时前
全球短信路由系统设计逻辑打破 80%送达率瓶颈:工程实践拆解
网络·网络协议·架构·gateway·信息与通信·paas
WIN-U64 小时前
新版华三H3C交换机配置NTP时钟步骤 示例(命令及WEB配置)
网络协议·tcp/ip·http
爱学习的小囧4 小时前
ESXi 8.0 无法选择分区方式 小白级详细解决办法
运维·服务器·网络·虚拟化·esxi8.0
F1FJJ4 小时前
什么是 Shield CLI?视频讲解:一条命令,可浏览器远程访问一切内部服务(RDP/VNC/SSH/数据库等)
运维·网络·数据库·网络协议·ssh
南湖北漠5 小时前
听说拍照的人会拿相似的鱼皮豆代替野生鹌鹑蛋拍照(防原创)
网络·人工智能·计算机网络·生活
一个有温度的技术博主5 小时前
网安实验系列四:信息收集-旁站、C段信息
网络
木下~learning5 小时前
对于Linux中等待队列和工作队列的讲解和使用|RK3399
linux·c语言·网络·模块化编程·工作队列·等待队列