zoukankan      html  css  js  c++  java
  • nginx对端口的处理 第三篇

    微信公众号:郑尔多斯
    关注可了解更多的Nginx知识。任何问题或建议,请公众号留言;
    关注公众号,有趣有内涵的文章第一时间送达!

    ngx_open_listening_sockets

      1ngx_int_t
    2ngx_open_listening_sockets(ngx_cycle_t *cycle)
    3{
    4    int               reuseaddr;
    5    ngx_uint_t        i, tries, failed;
    6    ngx_err_t         err;
    7    ngx_log_t        *log;
    8    ngx_socket_t      s;
    9    ngx_listening_t  *ls;
    10
    11    reuseaddr = 1;
    12#if (NGX_SUPPRESS_WARN)
    13    failed = 0;
    14#endif
    15
    16    log = cycle->log;
    17
    18    /* TODO: configurable try number */
    19
    20    for (tries = 5; tries; tries--) {
    21        failed = 0;
    22
    23        /* for each listening socket */
    24
    25        ls = cycle->listening.elts;
    26        for (i = 0; i < cycle->listening.nelts; i++) {
    27
    28            if (ls[i].ignore) {
    29                continue;
    30            }
    31
    32#if (NGX_HAVE_REUSEPORT)
    33
    34            if (ls[i].add_reuseport) {
    35
    36                /*
    37                 * to allow transition from a socket without SO_REUSEPORT
    38                 * to multiple sockets with SO_REUSEPORT, we have to set
    39                 * SO_REUSEPORT on the old socket before opening new ones
    40                 */

    41
    42                int  reuseport = 1;
    43
    44                if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
    45                               (const void *) &reuseport, sizeof(int))
    46                    == -1)
    47                {
    48                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
    49                                  "setsockopt(SO_REUSEPORT) %V failed, ignored",
    50                                  &ls[i].addr_text);
    51                }
    52
    53                ls[i].add_reuseport = 0;
    54            }
    55#endif
    56
    57            if (ls[i].fd != (ngx_socket_t-1) {
    58                continue;
    59            }
    60
    61            if (ls[i].inherited) {
    62
    63                /* TODO: close on exit */
    64                /* TODO: nonblocking */
    65                /* TODO: deferred accept */
    66
    67                continue;
    68            }
    69
    70            s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
    71
    72            if (s == (ngx_socket_t-1) {
    73                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    74                              ngx_socket_n " %V failed", &ls[i].addr_text);
    75                return NGX_ERROR;
    76            }
    77
    78            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
    79                           (const void *) &reuseaddr, sizeof(int))
    80                == -1)
    81            {
    82                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    83                              "setsockopt(SO_REUSEADDR) %V failed",
    84                              &ls[i].addr_text);
    85
    86                if (ngx_close_socket(s) == -1) {
    87                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    88                                  ngx_close_socket_n " %V failed",
    89                                  &ls[i].addr_text);
    90                }
    91
    92                return NGX_ERROR;
    93            }
    94
    95#if (NGX_HAVE_REUSEPORT)
    96
    97            if (ls[i].reuseport && !ngx_test_config) {
    98                int  reuseport;
    99
    100                reuseport = 1;
    101
    102                if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
    103                               (const void *) &reuseport, sizeof(int))
    104                    == -1)
    105                {
    106                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    107                                  "setsockopt(SO_REUSEPORT) %V failed",
    108                                  &ls[i].addr_text);
    109
    110                    if (ngx_close_socket(s) == -1) {
    111                        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    112                                      ngx_close_socket_n " %V failed",
    113                                      &ls[i].addr_text);
    114                    }
    115
    116                    return NGX_ERROR;
    117                }
    118            }
    119#endif
    120
    121#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
    122
    123            if (ls[i].sockaddr->sa_family == AF_INET6) {
    124                int  ipv6only;
    125
    126                ipv6only = ls[i].ipv6only;
    127
    128                if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
    129                               (const void *) &ipv6only, sizeof(int))
    130                    == -1)
    131                {
    132                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    133                                  "setsockopt(IPV6_V6ONLY) %V failed, ignored",
    134                                  &ls[i].addr_text);
    135                }
    136            }
    137#endif
    138            /* TODO: close on exit */
    139
    140            if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
    141                if (ngx_nonblocking(s) == -1) {
    142                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    143                                  ngx_nonblocking_n " %V failed",
    144                                  &ls[i].addr_text);
    145
    146                    if (ngx_close_socket(s) == -1) {
    147                        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    148                                      ngx_close_socket_n " %V failed",
    149                                      &ls[i].addr_text);
    150                    }
    151
    152                    return NGX_ERROR;
    153                }
    154            }
    155
    156            ngx_log_debug2(NGX_LOG_DEBUG_CORE, log0,
    157                           "bind() %V #%d ", &ls[i].addr_text, s);
    158
    159            if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
    160                err = ngx_socket_errno;
    161
    162                if (err != NGX_EADDRINUSE || !ngx_test_config) {
    163                    ngx_log_error(NGX_LOG_EMERG, log, err,
    164                                  "bind() to %V failed", &ls[i].addr_text);
    165                }
    166
    167                if (ngx_close_socket(s) == -1) {
    168                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    169                                  ngx_close_socket_n " %V failed",
    170                                  &ls[i].addr_text);
    171                }
    172
    173                if (err != NGX_EADDRINUSE) {
    174                    return NGX_ERROR;
    175                }
    176
    177                if (!ngx_test_config) {
    178                    failed = 1;
    179                }
    180
    181                continue;
    182            }
    183
    184#if (NGX_HAVE_UNIX_DOMAIN)
    185
    186            if (ls[i].sockaddr->sa_family == AF_UNIX) {
    187                mode_t   mode;
    188                u_char  *name;
    189
    190                name = ls[i].addr_text.data + sizeof("unix:") - 1;
    191                mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
    192
    193                if (chmod((char *) name, mode) == -1) {
    194                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
    195                                  "chmod() \"%s\" failed", name);
    196                }
    197
    198                if (ngx_test_config) {
    199                    if (ngx_delete_file(name) == NGX_FILE_ERROR) {
    200                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
    201                                      ngx_delete_file_n " %s failed", name);
    202                    }
    203                }
    204            }
    205#endif
    206
    207            if (ls[i].type != SOCK_STREAM) {
    208                ls[i].fd = s;
    209                continue;
    210            }
    211
    212            if (listen(s, ls[i].backlog) == -1) {
    213                err = ngx_socket_errno;
    214
    215                /*
    216                 * on OpenVZ after suspend/resume EADDRINUSE
    217                 * may be returned by listen() instead of bind(), see
    218                 * https://bugzilla.openvz.org/show_bug.cgi?id=2470
    219                 */

    220
    221                if (err != NGX_EADDRINUSE || !ngx_test_config) {
    222                    ngx_log_error(NGX_LOG_EMERG, log, err,
    223                                  "listen() to %V, backlog %d failed",
    224                                  &ls[i].addr_text, ls[i].backlog);
    225                }
    226
    227                if (ngx_close_socket(s) == -1) {
    228                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
    229                                  ngx_close_socket_n " %V failed",
    230                                  &ls[i].addr_text);
    231                }
    232
    233                if (err != NGX_EADDRINUSE) {
    234                    return NGX_ERROR;
    235                }
    236
    237                if (!ngx_test_config) {
    238                    failed = 1;
    239                }
    240
    241                continue;
    242            }
    243
    244            ls[i].listen = 1;
    245
    246            ls[i].fd = s;
    247        }
    248
    249        if (!failed) {
    250            break;
    251        }
    252
    253        /* TODO: delay configurable */
    254
    255        ngx_log_error(NGX_LOG_NOTICE, log0,
    256                      "try again to bind() after 500ms");
    257
    258        ngx_msleep(500);
    259    }
    260
    261    if (failed) {
    262        ngx_log_error(NGX_LOG_EMERG, log0"still could not bind()");
    263        return NGX_ERROR;
    264    }
    265
    266    return NGX_OK;
    267}

    这个函数的功能很简单,就是打开socket,然后bind,然后listen,仅此而已,通过这个函数,我么已经对这个端口和IP地址进行了listen,当有新的连接的时候,就会accept新的连接。
    内存布局如下:

    内存布局内存布局

    喜欢本文的朋友们,欢迎长按下图关注订阅号郑尔多斯,更多精彩内容第一时间送达

    郑尔多斯郑尔多斯
  • 相关阅读:
    求求你规范下你的代码风格
    为啥用ip不可以访问知乎,而百度却可以?
    漫画:htts是如何保证一台主机把数据安全发给另一台主机
    如何从亿量级中判断一个数是否存在?
    广播路由算法 :我是如何优雅着把悄悄话带给其他人的
    什么?你不知道0.0.0.0和255.255.255.255这两个地址是干嘛的?
    一篇文章带你学会Linux三剑客之一:awk
    你真的了解 i++, ++i 和 i+++++i 以及 i+++i++ 吗?
    通俗易懂讲解TCP流量控制机制,了解一下
    一文读懂拥塞控制
  • 原文地址:https://www.cnblogs.com/zhengerduosi/p/10087975.html
Copyright © 2011-2022 走看看