nginx的 ngx_listening_s 模块(未完成)

结构

ngx_listening_s :监听套接字文件描述
struct ngx_listening_s {
    ngx_socket_t        fd; //套接字

    struct sockaddr    *sockaddr;   //监听的地址
    socklen_t           socklen;    /* 地址长度*/
    size_t              addr_text_max_len;  '存储ip地址的字符串 addr_text 最大长度'
    ngx_str_t           addr_text;  '以字符串存储的ip地址'

    int                 type;   //套接字类型。types是SOCK_STREAM时,表示是tcp

    int                 backlog;    '记录监听套接字的链接数大小(2个队列:完成3次链接和未完成3次链接)'
    int                 rcvbuf;     //套接字接收进程缓冲区大小 
    int                 sndbuf;     //套接字发送进程缓冲区大小  
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
    int                 keepidle;
    int                 keepintvl;
    int                 keepcnt;
#endif

    /* handler of accepted connection */
    ngx_connection_handler_pt   handler;    '当新的tcp链接成功创建后的处理方法 '

    void               *servers;  '目前主要用于HTTP或者mail等模块,用于保存当前监听端口对应着的全部主机名  '

    ngx_log_t           log;
    ngx_log_t          *logp;

    size_t              pool_size;  '若是为新的tcp链接建立内存池,则内存池的初始大小应该是pool_size'
    /* should be here because of the AcceptEx() preread */
    size_t              post_accept_buffer_size;    '接受事件的buffer大小'
    /* should be here because of the deferred accept */
    ngx_msec_t          post_accept_timeout;        '接受事件的超时时间'

    ngx_listening_t    *previous;   '前一个ngx_listening_t结构,用于组成单链表'
    ngx_connection_t   *connection; '监听链接池的第一个指针'

    ngx_uint_t          worker; '工做进程的个数'

    unsigned            open:1; '当前套接字,为1表示监听句柄有效,为0表示正常关闭 '
    unsigned            remain:1;   '为1表示不关闭原先打开的监听端口,为0表示关闭曾经打开的监听端口'
    unsigned            ignore:1;   '为1表示跳过设置当前ngx_listening_t结构体中的套接字,为0时正常初始化套接字 '

    unsigned            bound:1;       '是否已绑定'
    unsigned            inherited:1;    '是否从上一个进程中继承'
    unsigned            nonblocking_accept:1;   '是否非阻塞接受'
    unsigned            listen:1;       '是否为1表示当前结构体对应的套接字已经监听 '
    unsigned            nonblocking:1;  '是否非阻塞接受'
    unsigned            shared:1;    /* shared between threads or processes */
    unsigned            addr_ntop:1;    '为1表示将网络地址转变为字符串形式的地址'
    unsigned            wildcard:1;


    unsigned            reuseport:1;
    unsigned            add_reuseport:1;
    unsigned            keepalive:2;

    unsigned            deferred_accept:1;
    unsigned            delete_deferred:1;
    unsigned            add_deferred:1;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
    char               *accept_filter;
#endif
#if (NGX_HAVE_SETFIB)
    int                 setfib;
#endif

#if (NGX_HAVE_TCP_FASTOPEN)
    int                 fastopen;
#endif

};
  • backlog半链接状态和全链接状态两种队列大小
    •  半链接状态为:服务器处于Listen状态时收到客户端SYN=1报文时放入半链接队列中,即SYN queue(服务器端口状态为:SYN_RCVD)。
    •  全链接状态为:TCP的链接状态从服务器 (SYN+ACK) 响应客户端后,到客户端的ACK报文到达服务器以前,则一直保留在半链接状态中;当服务器接收到客户端的ACK报文后,该条目将从半链接队列搬到全链接队列尾部,即 accept queue (服务器端口状态为:ESTABLISHED)。
ngx_connection_s 链接套接字
// 事件结构
struct ngx_connection_s {
    void               *data;   //链接未使用时,data用于充当链接池中空闲链表中的next指针。有链接套接字使用时,由模块而定:http中,data指向ngx_http_connection_t
    ngx_event_t        *read;   //链接对应的读事件
    ngx_event_t        *write;  //链接对应的写事件

    ngx_socket_t        fd;     //套接字描述符

    ngx_recv_pt         recv;   //接受网络字符流的方法
    ngx_send_pt         send;   ///发送网络字符流的方法
    ngx_recv_chain_pt   recv_chain; //链表来表示结束网络字符流的方法
    ngx_send_chain_pt   send_chain; //链表来表示发送网络字符流的方法

    ngx_listening_t    *listening;  //链接对应的ngx_listening_t监听的对象,此链接由listening监听端口的事件创建

    off_t               sent;   //链接上已发送的字符数

    ngx_log_t          *log;    //日志对象

    ngx_pool_t         *pool;   //内存池

    int                 type;   //

    struct sockaddr    *sockaddr;   //链接客户端的sockaddr
    socklen_t           socklen;    //sockaddr结构体的长度
    ngx_str_t           addr_text;  //链接客户端字符串形式的IP地址

    ngx_str_t           proxy_protocol_addr;    //协议地址
    in_port_t           proxy_protocol_port;    //协议端口

#if (NGX_SSL || NGX_COMPAT)
    ngx_ssl_connection_t  *ssl;
#endif

    struct sockaddr    *local_sockaddr; //本机监听端口对应的sockaddr结构体,其实是listening监听对象的sockaddr对象
    socklen_t           local_socklen;  //监听端口个数

    //用户接受、缓存客户端发来的字符流
    //buffer是由链接内池分配,大小自由决定
    ngx_buf_t          *buffer; 

    //用来将当前链接以双向链表元素的形式添加到ngx_cycle_t核心结构体的reuseable_connection_queue双向链表中,表示能够重用的链接
    ngx_queue_t         queue;

    ngx_atomic_uint_t   number; //链接使用次数。ngx_connection_t结构体每次创建一条来自客户端的链接,或主动向后端服务器发起链接时,number都会加1

    ngx_uint_t          requests;   //处理请求的次数

    unsigned            buffered:8; //缓存业务类型

    unsigned            log_error:3;     /* ngx_connection_log_error_e */

    unsigned            timedout:1;//为1表示链接已经超时  
    unsigned            error:1;//为1表示链接处理过程当中出现错误  
    unsigned            destroyed:1;//为1表示链接已经销毁  

    unsigned            idle:1;//为1表示链接处于空闲状态,如keepalive两次请求中间的状态  
    unsigned            reusable:1;//为1表示链接可重用,与上面的queue字段对应使用  
    unsigned            close:1;//为1表示链接关闭  
    unsigned            shared:1;

    unsigned            sendfile:1;//为1表示正在将文件中的数据发往链接的另外一端  
    unsigned            sndlowat:1;
    unsigned            tcp_nodelay:2;   /* ngx_connection_tcp_nodelay_e */
    unsigned            tcp_nopush:2;    /* ngx_connection_tcp_nopush_e */
     /*为1表示只有链接套接字对应的发送缓冲区必须知足最低设置的大小阀值时,
     事件驱动模块才会分发该事件。这与ngx_handle_write_event方法中的lowat参数是对应的*/  
    unsigned            need_last_buf:1;

#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
    unsigned            busy_count:2;
#endif

#if (NGX_THREADS || NGX_COMPAT)
    ngx_thread_task_t  *sendfile_task;
#endif
};

函数

建立监听套接字配置空间:主要是在初始化的cycle时,建立的配置空间
/**
    ngx_conf_t:配置文件
    sockaddr:监听地址
    socklen:地址长度
*/
ngx_listening_t *
ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
    socklen_t socklen)
{
    size_t            len;
    ngx_listening_t  *ls;
    struct sockaddr  *sa;
    u_char            text[NGX_SOCKADDR_STRLEN];

    ls = ngx_array_push(&cf->cycle->listening);
    if (ls  NULL) {
        return NULL;
    }

    ngx_memzero(ls, sizeof(ngx_listening_t));

    sa = ngx_palloc(cf->pool, socklen);
    if (sa  NULL) {
        return NULL;
    }

    ngx_memcpy(sa, sockaddr, socklen);

    ls->sockaddr = sa;
    ls->socklen = socklen;

    len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
    ls->addr_text.len = len;

    switch (ls->sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
    case AF_INET6:
        ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
        break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
    case AF_UNIX:
        ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
        len++;
        break;
#endif
    case AF_INET:
        ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
        break;
    default:
        ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
        break;
    }

    ls->addr_text.data = ngx_pnalloc(cf->pool, len);
    if (ls->addr_text.data  NULL) {
        return NULL;
    }

    ngx_memcpy(ls->addr_text.data, text, len);

    ls->fd = (ngx_socket_t) -1;
    ls->type = SOCK_STREAM;

    ls->backlog = NGX_LISTEN_BACKLOG;
    ls->rcvbuf = -1;
    ls->sndbuf = -1;

#if (NGX_HAVE_SETFIB)
    ls->setfib = -1;
#endif

#if (NGX_HAVE_TCP_FASTOPEN)
    ls->fastopen = -1;
#endif

    return ls;
}
初始化客户端链接的套接字
相关文章
相关标签/搜索