首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

nginx源码分析(五)——监听socket初始化

2012-07-29 
nginx源码分析(5)——监听socket初始化在nginx源码分析(4)中,看到了nginx的事件模型,但其中没有介绍监听sock

nginx源码分析(5)——监听socket初始化

        在nginx源码分析(4)中,看到了nginx的事件模型,但其中没有介绍监听socket的初始化。而对于web server来说,需要通过监听socket来监听客户端的连接等。本篇将会具体介绍这方面的内容。还记得在前文介绍ngx_cycle_t结构时,它具有一个listening属性,是一个数组,存储所有监听socket,下面就来看看这些信息是什么时候添加的、以及如何初始化的。

1. 重要的数据结构

        1. ngx_http_conf_port_t

        监听端口配置信息,addrs是在该端口上所有监听地址的数组。

voidngx_configure_listening_sockets(ngx_cycle_t *cycle){    ngx_uint_t                 i;    ngx_listening_t           *ls;#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)    struct accept_filter_arg   af;#endif#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)    int                        timeout;#endif    ls = cycle->listening.elts;    for (i = 0; i < cycle->listening.nelts; i++) {        ls[i].log = *ls[i].logp;        /**         * 设置监听socket的接收缓冲区大小         */        if (ls[i].rcvbuf != -1) {            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,                           (const void *) &ls[i].rcvbuf, sizeof(int))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,                              "setsockopt(SO_RCVBUF, %d) %V failed, ignored",                              ls[i].rcvbuf, &ls[i].addr_text);            }        }        /**         * 设置监听socket的发送缓冲区大小         */        if (ls[i].sndbuf != -1) {            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,                           (const void *) &ls[i].sndbuf, sizeof(int))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,                              "setsockopt(SO_SNDBUF, %d) %V failed, ignored",                              ls[i].sndbuf, &ls[i].addr_text);            }        }#if (NGX_HAVE_SETFIB)        if (ls[i].setfib != -1) {            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,                           (const void *) &ls[i].setfib, sizeof(int))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,                              "setsockopt(SO_SETFIB, %d) %V failed, ignored",                              ls[i].setfib, &ls[i].addr_text);            }        }#endif#if 0        if (1) {            int tcp_nodelay = 1;            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,                       (const void *) &tcp_nodelay, sizeof(int))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,                              "setsockopt(TCP_NODELAY) %V failed, ignored",                              &ls[i].addr_text);            }        }#endif        if (ls[i].listen) {            /* change backlog via listen() */            if (listen(ls[i].fd, ls[i].backlog) == -1) {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,                              "listen() to %V, backlog %d failed, ignored",                              &ls[i].addr_text, ls[i].backlog);            }        }        /*         * setting deferred mode should be last operation on socket,         * because code may prematurely continue cycle on failure         */#if (NGX_HAVE_DEFERRED_ACCEPT)#ifdef SO_ACCEPTFILTER        if (ls[i].delete_deferred) {        /**         * set accept filter on listening socket         * 将SO_ACCEPTFILTER设置为NULL,也就是删除accept filter         */            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                              "setsockopt(SO_ACCEPTFILTER, NULL) "                              "for %V failed, ignored",                              &ls[i].addr_text);                if (ls[i].accept_filter) {                    ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,                                  "could not change the accept filter "                                  "to \"%s\" for %V, ignored",                                  ls[i].accept_filter, &ls[i].addr_text);                }                continue;            }            ls[i].deferred_accept = 0;        }        if (ls[i].add_deferred) {            ngx_memzero(&af, sizeof(struct accept_filter_arg));            (void) ngx_cpystrn((u_char *) af.af_name,                               (u_char *) ls[i].accept_filter, 16);            /**             * set accept filter on listening socket         * 将SO_ACCEPTFILTER设置为ls[i].accept_filter,也就是添加accept filter             */            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,                           &af, sizeof(struct accept_filter_arg))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                              "setsockopt(SO_ACCEPTFILTER, \"%s\") "                              " for %V failed, ignored",                              ls[i].accept_filter, &ls[i].addr_text);                continue;            }            ls[i].deferred_accept = 1;        }#endif#ifdef TCP_DEFER_ACCEPT        if (ls[i].add_deferred || ls[i].delete_deferred) {            if (ls[i].add_deferred) {                timeout = (int) (ls[i].post_accept_timeout / 1000);            } else {                timeout = 0;            }            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,                           &timeout, sizeof(int))                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                              "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "                              "ignored",                              timeout, &ls[i].addr_text);                continue;            }        }        if (ls[i].add_deferred) {            ls[i].deferred_accept = 1;        }#endif#endif /* NGX_HAVE_DEFERRED_ACCEPT */    }    return;}
        这个函数就是根据配置调用setsockopt函数设置socket选项,比如接收缓冲区、发送缓冲区等,具体也没有什么可讲的。
        通过这3个步骤就完成了监听socket的初始化,接下来就会在ngx_event_process_init函数(ngx_event_core_moduel的process_init回调函数,在创建完worker进程后调用)中将这些监听socket添加到事件循环中。



热点排行