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;
}
初始化客戶端鏈接的套接字
相關文章
相關標籤/搜索