来源《深入理解nginx模块开发与架构解析》
typedef struct ngx_connection_s ngx_connection_t;
struct ngx_connection_s {
/*连接未使用时, data成员用于充当连接池中空闲连接链表中的 next指针。
当连接被使用时, data的意义由使用它的 Nginx模块而定,
如在 HTTP框架中, data指向 ngx_http_request_t请求 */
void *data;
// 连接对应的读事件
ngx_event_t *read;
// 连接对应的写事件
ngx_event_t *write;
// 套接字句柄
ngx_socket_t fd;
// 直接接收网络字符流的方法
ngx_recv_pt recv;
// 直接发送网络字符流的方法
ngx_send_pt send;
// 以 ngx_chain_t链表为参数来接收网络字符流的方法
ngx_recv_chain_pt recv_chain;
// 以 ngx_chain_t链表为参数来发送网络字符流的方法
ngx_send_chain_pt send_chain;
/*这个连接对应的 ngx_listening_t监听对象,
此连接由 listening监听端口的事件建立 */
ngx_listening_t *listening;
// 这个连接上已经发送出去的字节数
off_t sent;
// 可以记录日志的 ngx_log_t对象
ngx_log_t *log;
/*内存池。一般在 accept一个新连接时,会创建一个内存池,
而在这个连接结束时会销毁内存池。注意,这里所说的连接是指成功建立的 TCP连接,
所有的 ngx_connection_t结构体都是预分配的。这个内存池的大小将由上面的 listening监听对象中的 pool_size成员决定 */
ngx_pool_t *pool;
// 连接客户端的 sockaddr结构体
struct sockaddr *sockaddr;
// sockaddr结构体的长度
socklen_t socklen;
// 连接客户端字符串形式的 IP地址
ngx_str_t addr_text;
/*本机的监听端口对应的 sockaddr结构体,
也就是 listening监听对象中的 sockaddr成员 */
struct sockaddr *local_sockaddr;
/*用于接收、缓存客户端发来的字符流,每个事件消费模块可自由决定从连接池中分配多大的空间给 buffer这个接收缓存字段。
例如,在 HTTP模块中,它的大小决定于 client_header_buffer_size配置项 */
ngx_buf_t *buffer;
/*该字段用来将当前连接以双向链表元素的形式添加到ngx_cycle_t核心结构体的 reusable_connections_queue双向链表中,
表示可以重用的连接 */
ngx_queue_t queue;
/*连接使用次数。 ngx_connection_t结构体每次建立一条来自客户端的连接,
或者用于主动向后端服务器发起连接时( ngx_peer_connection_t也使用它), number都会加 1*/
ngx_atomic_uint_t number; // 处理的请求次数 ngx_uint_t requests;
/*缓存中的业务类型。任何事件消费模块都可以自定义需要的标志位。这个 buffered字段有 8位,最多可以同时表示 8个不同的业务。
第三方模块在自定义 buffered标志位时注意不要与可能使用的模块定义的标志位冲突。
目前openssl模块定义了一个标志位: #define NGX_SSL_BUFFERED 0x01
HTTP官方模块定义了以下标志位: #define NGX_HTTP_LOWLEVEL_BUFFERED 0xf0
#define NGX_HTTP_WRITE_BUFFERED 0x10
#define NGX_HTTP_GZIP_BUFFERED 0x20
#define NGX_HTTP_SSI_BUFFERED 0x01
#define NGX_HTTP_SUB_BUFFERED 0x02
#define NGX_HTTP_COPY_BUFFERED 0x04
#define NGX_HTTP_IMAGE_BUFFERED 0x08
同时,对于 HTTP模块而言, buffered的低 4位要慎用,在实际发送响应的 ngx_http_write_filter_module过滤模块中,
低 4位标志位为 1则意味着 Nginx会一直认为有 HTTP模块还需要处理这个请求,必须等待
HTTP模块将低 4位全置为 0才会正常结束请求。检查低 4位的宏如下: #define NGX_LOWLEVEL_BUFFERED 0x0f */
unsigned buffered:8;
/*本连接记录日志时的级别,它占用了 3位,取值范围是 0~7,但实际上目前只定义了 5个值,由 ngx_connection_log_error_e枚举表示,
如下: typedef enum { NGX_ERROR_ALERT = 0, NGX_ERROR_ERR, NGX_ERROR_INFO, NGX_ERROR_IGNORE_ECONNRESET, NGX_ERROR_IGNORE_EINVAL } ngx_connection_log_error_e; */
unsigned log_error:3;
/*标志位,为 1时表示独立的连接,如从客户端发起的连接;为 0时表示依靠其他连接的行为而建立起来的非独立连接,
如使用 upstream机制向后端服务器建立起来的连接 */
unsigned single_connection:1;
// 标志位,为 1时表示不期待字符流结束,目前无意义
unsigned unexpected_eof:1;
// 标志位,为 1时表示连接已经超时
unsigned timedout:1;
// 标志位,为 1时表示连接处理过程中出现错误
unsigned error:1;
/*标志位,为 1时表示连接已经销毁。这里的连接指是的 TCP连接,而不是 ngx_connection_t结构体。
当 destroyed为 1时, ngx_connection_t结构体仍然存在,但其对应的套接字、内存池等已经不可用 */
unsigned destroyed:1;
/*标志位,为 1时表示连接处于空闲状态,如 keepalive请求中两次请求之间的状态 */
unsigned idle:1;
// 标志位,为 1时表示连接可重用,它与上面的 queue字段是对应使用的
unsigned reusable:1;
// 标志位,为 1时表示连接关闭
unsigned close:1;
// 标志位,为 1时表示正在将文件中的数据发往连接的另一端
unsigned sendfile:1;
/*标志位,如果为 1,则表示只有在连接套接字对应的发送缓冲区必须满足最低设置的大小阈值时,
事件驱动模块才会分发该事件。这与上文介绍过的 ngx_handle_write_event方法中的 lowat参数是对应的 */
unsigned sndlowat:1;
/*标志位,表示如何使用 TCP的 nodelay特性。它的取值范围是下面这个枚举类型 ngx_connection_tcp_nodelay_e:
typedef enum { NGX_TCP_NODELAY_UNSET = 0, NGX_TCP_NODELAY_SET, NGX_TCP_NODELAY_DISABLED } ngx_connection_tcp_nodelay_e; */
unsigned tcp_nodelay:2;
/*标志位,表示如何使用 TCP的 nopush特性。它的取值范围是下面这个枚举类型
ngx_connection_tcp_nopush_e: typedef enum { NGX_TCP_NOPUSH_UNSET = 0, NGX_TCP_NOPUSH_SET, NGX_TCP_NOPUSH_DISABLED } ngx_connection_tcp_nopush_e; */
unsigned tcp_nopush:2;
#if (NGX_HAVE_AIO_SENDFILE)
// 标志位,为 1时表示使用异步 I/O的方式将磁盘上文件发送给网络连接的另一端
unsigned aio_sendfile:1;
// 使用异步 I/O方式发送的文件, busy_sendfile缓冲区保存待发送文件的信息
ngx_buf_t *busy_sendfile;
#endif
}