1 定义 ngx_close_accepted_connection 函数 定义在 ./nginx-1.24.0/src/event/ngx_event_accept.cstatic void ngx_close_accepted_connection ( ngx_connection_t * c) { ngx_socket_t fd; ngx_free_connection ( c) ; fd= c-> fd; c-> fd= ( ngx_socket_t ) - 1 ; if ( ngx_close_socket ( fd) == - 1 ) { ngx_log_error ( NGX_LOG_ALERT, c-> log, ngx_socket_errno, ngx_close_socket_n" failed" ) ; } if ( c-> pool) { ngx_destroy_pool ( c-> pool) ; } # if ( NGX_STAT_STUB) ( void ) ngx_atomic_fetch_add ( ngx_stat_active, - 1 ) ; # endif } ngx_close_accepted_connection 函数 负责彻底关闭一个已被接受的客户端连接,释放所有相关资源。 它在连接处理完成、出错或超时等场景下被调用,是连接生命周期终结时的核心清理函数。2 详解 1 函数签名 static void ngx_close_accepted_connection ( ngx_connection_t * c) 无返回值参数 ngx_connection_t *c 指向要被清理的连接2 逻辑流程 1 局部变量 2 释放连接 3 关闭底层 socket 4 销毁内存池 5 更新活跃连接统计1 局部变量{ ngx_socket_t fd; fd 用于暂存即将关闭的套接字文件描述符。 因为之后需要把连接结构体中的 fd 置为无效,必须提前保存原值。2 释放连接ngx_free_connection ( c) ; 归还连接结构体: 调用 ngx_free_connection 将连接对象 c 回收到 Nginx 的空闲连接池(或空闲链表)中。 此后该连接结构可被重新分配给新连接。 注意此时真正的 socket 还未关闭, 内存池也未销毁,只是让“壳”(连接元数据结构)变得可复用。3 关闭底层 socketfd= c-> fd; c-> fd= ( ngx_socket_t ) - 1 ; 暂存套接字描述符: 把连接结构中的 socket 描述符值复制到局部变量 fd,为后续真正的关闭操作做准备。 因为接下来 c->fd 会被改为 -1。 标记文件描述符无效:将连接结构中的 fd 置为 -1。 这是一个防御性编程手段,防止连接对象复用时意外操作到一个已经关闭或即将关闭的 socket, 也便于调试时识别无效状态。if ( ngx_close_socket ( fd) == - 1 ) { ngx_log_error ( NGX_LOG_ALERT, c-> log, ngx_socket_errno, ngx_close_socket_n" failed" ) ; } 关闭底层 socket: 调用操作系统级别的 socket 关闭函数(如 close 或 closesocket)。 如果返回 -1 表示关闭出错(例如已经被关闭、无效描述符等错误),进入错误处理分支。4 销毁内存池if ( c-> pool) { ngx_destroy_pool ( c-> pool) ; } 检查内存池是否存在: 每个连接通常拥有一个专属的内存池 c->pool, 用于分配读写缓冲区、请求结构等动态数据。 这里判断其非空,再执行销毁。 销毁内存池: 释放该连接对应内存池中的所有内存。 这一步会回收所有从该池分配的内存块,包括请求处理过程中产生的大量临时数据。 销毁之后,连接相关的全部动态资源得到彻底清理。5 更新活跃连接统计# if ( NGX_STAT_STUB) ( void ) ngx_atomic_fetch_add ( ngx_stat_active, - 1 ) ; # endif } 条件编译的活跃连接统计更新: 如果 Nginx 编译时开启了状态统计功能(NGX_STAT_STUB), 则调用原子减法操作将全局变量 ngx_stat_active 减 1, 表示当前活跃连接数减少一个。 (void) 显式丢弃返回值,强调只关心副作用。 该统计值用于 stub_status 模块等场合,提供 “Active connections” 指标。总结: 先归还连接结构(ngx_free_connection): 使连接对象尽早可复用,提高并发场景下连接池的周转效率。 再关闭 socket: 在归还结构后依然能安全关闭, 因为已提前备份 fd,且将原结构中的 fd 置为 -1 消除了误用风险。 然后销毁内存池: 此时连接已经与 socket 无关,释放所有动态内存不会影响其他逻辑。 最后更新统计: 在所有清理工作完成后才减少活跃连接计数,确保统计信息的准确性。