Heim >Betrieb und Instandhaltung >Nginx >So verwenden Sie den Listen-Befehl in Nginx
listen-Befehl
nginx ist ein leistungsstarker HTTP-Server, dessen Kern das Verständnis der Netzwerkinitialisierung ist, um Ihr Verständnis der Nginx-Netzwerkverarbeitung zu vertiefen. Es gibt zwei Hauptkonfigurationsbefehle für das Netzwerk: listen und sever_name. Der Listen-Befehl legt die Nginx-Abhöradresse fest. Für das Unix-Domänen-Socket-Protokoll kann ein Listen-Befehl nur eine Adresse oder einen Port angeben sei der Hostname
Ausgehend von diesem Artikel analysieren wir den Parsing-Prozess der Listen-Anweisung. Die Konfiguration der Listen-Anweisung ist wie folgt: Aus dem nginx.org-Handbuch können wir die Verwendung von listen:
listen address[:port] [default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [ssl] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
The entnehmen Parameter, die von einer Listen-Anweisung getragen werden, sind sehr komplex. Allerdings schenken wir diesen weniger häufig verwendeten Parametern im Allgemeinen wenig Aufmerksamkeit. Im Folgenden sind einige häufig verwendete Konfigurationsmethoden aufgeführt:
listen 127.0.0.1:8000; listen 127.0.0.1 不加端口,默认监听80端口; listen 8000 listen *:8000 listen localhost:8000
Parsen der URI und des Ports im Listen-Befehl
Wie wir aus dem obigen Inhalt wissen, hat listen viele Verwendungsmöglichkeiten . Beim Parsen müssen Sie die Portnummer und den URL-Teil der Listen-Anweisung abrufen. Nginx stellt die Methode ngx_parse_url () zum Parsen der URL und des Ports bereit.
ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) { u_char *p; size_t len; p = u->url.data; len = u->url.len; // 这里是解析unix domain的协议 if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { return ngx_parse_unix_domain_url(pool, u); } // 解析ipv6协议 if (len && p[0] == '[') { return ngx_parse_inet6_url(pool, u); } // 解析ipv4协议 return ngx_parse_inet_url(pool, u); }
Wir verwenden das IPv4-Protokoll.
// u.url = "80"; // u.listen = 1; // u.default_port = 80; static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) { u_char *p, *host, *port, *last, *uri, *args; size_t len; ngx_int_t n; struct sockaddr_in *sin; #if (ngx_have_inet6) struct sockaddr_in6 *sin6; #endif u->socklen = sizeof(struct sockaddr_in); sin = (struct sockaddr_in *) &u->sockaddr; sin->sin_family = af_inet;// ipv4类型 u->family = af_inet; host = u->url.data; // "80" last = host + u->url.len; // host的最后字符的位置 port = ngx_strlchr(host, last, ':'); // 找到port, 这里为 null uri = ngx_strlchr(host, last, '/'); // 找到uri,这里为 null args = ngx_strlchr(host, last, '?'); // 找到参数args,这里为 null if (args) { if (uri == null || args < uri) { uri = args; } } if (uri) { if (u->listen || !u->uri_part) { u->err = "invalid host"; return ngx_error; } u->uri.len = last - uri; u->uri.data = uri; last = uri; if (uri < port) { port = null; } } if (port) { port++; len = last - port; n = ngx_atoi(port, len); if (n < 1 || n > 65535) { u->err = "invalid port"; return ngx_error; } u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); u->port_text.len = len; u->port_text.data = port; last = port - 1; } else { if (uri == null) { if (u->listen) { /* test value as port only */ n = ngx_atoi(host, last - host); if (n != ngx_error) { if (n < 1 || n > 65535) { u->err = "invalid port"; return ngx_error; } u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); u->port_text.len = last - host; u->port_text.data = host; u->wildcard = 1; return ngx_ok; } } } u->no_port = 1; u->port = u->default_port; sin->sin_port = htons(u->default_port); } len = last - host; if (len == 0) { u->err = "no host"; return ngx_error; } u->host.len = len; u->host.data = host; if (u->listen && len == 1 && *host == '*') { sin->sin_addr.s_addr = inaddr_any; u->wildcard = 1; return ngx_ok; } sin->sin_addr.s_addr = ngx_inet_addr(host, len); if (sin->sin_addr.s_addr != inaddr_none) { if (sin->sin_addr.s_addr == inaddr_any) { u->wildcard = 1; } u->naddrs = 1; u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); if (u->addrs == null) { return ngx_error; } sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); if (sin == null) { return ngx_error; } ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); u->addrs[0].sockaddr = (struct sockaddr *) sin; u->addrs[0].socklen = sizeof(struct sockaddr_in); p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); if (p == null) { return ngx_error; } u->addrs[0].name.len = ngx_sprintf(p, "%v:%d", &u->host, u->port) - p; u->addrs[0].name.data = p; return ngx_ok; } if (u->no_resolve) { return ngx_ok; } if (ngx_inet_resolve_host(pool, u) != ngx_ok) { return ngx_error; } u->family = u->addrs[0].sockaddr->sa_family; u->socklen = u->addrs[0].socklen; ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); switch (u->family) { #if (ngx_have_inet6) case af_inet6: sin6 = (struct sockaddr_in6 *) &u->sockaddr; if (in6_is_addr_unspecified(&sin6->sin6_addr)) { u->wildcard = 1; } break; #endif default: /* af_inet */ sin = (struct sockaddr_in *) &u->sockaddr; if (sin->sin_addr.s_addr == inaddr_any) { u->wildcard = 1; } break; } return ngx_ok; }
Diese Funktion analysiert die Adresse und Portnummer unseres Abhörens. In unserer Konfigurationsdatei ist die Portnummer 80 und es gibt kein Abhören Adresse konfiguriert. u->wildcard = 1 bedeutet also, dass es sich um einen Platzhalter handelt und Sie diese Portnummer aller IP-Adressen des Servers abhören möchten.
Parsen des Listen-Befehls
Werfen wir einen Blick auf die Listen-Konfiguration aus dem Quellcode:
{ ngx_string("listen"), ngx_http_srv_conf|ngx_conf_1more, ngx_http_core_listen, ngx_http_srv_conf_offset, 0, null }
Aus der Konfigurationsdatei können wir erkennen, dass listen nur im Servermodul erscheinen und mehrere Parameter haben kann.
Die entsprechende Verarbeitungsfunktion ist ngx_http_core_listen. Wir haben einige Fehlerbeurteilungscodes gelöscht.
static char * ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_srv_conf_t *cscf = conf; ngx_str_t *value, size; ngx_url_t u; ngx_uint_t n; ngx_http_listen_opt_t lsopt; cscf->listen = 1; value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; u.default_port = 80; if (ngx_parse_url(cf->pool, &u) != ngx_ok) { return ngx_conf_error; } ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); lsopt.socklen = u.socklen; lsopt.backlog = ngx_listen_backlog; lsopt.rcvbuf = -1; lsopt.sndbuf = -1; #if (ngx_have_setfib) lsopt.setfib = -1; #endif #if (ngx_have_tcp_fastopen) lsopt.fastopen = -1; #endif lsopt.wildcard = u.wildcard; #if (ngx_have_inet6) lsopt.ipv6only = 1; #endif (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, ngx_sockaddr_strlen, 1); for (n = 2; n < cf->args->nelts; n++) { if (ngx_strcmp(value[n].data, "default_server") == 0 || ngx_strcmp(value[n].data, "default") == 0) { lsopt.default_server = 1; continue; } // 这里面的其他代码都是处理listen的各种参数,对我们这里的分析没有用处 } if (ngx_http_add_listen(cf, cscf, &lsopt) == ngx_ok) { return ngx_conf_ok; } return ngx_conf_error; }
Der Gesamtprozess dieser Funktion besteht darin, jeden Parameter der Listen-Anweisung zu analysieren Der Name legt nahe, dass die Struktur darin besteht, einige Abhörportoptionen (Abhörportoptionen) zu speichern. Hier wird eine Funktion ngx_parse_url() aufgerufen. Wir haben sie oben analysiert. Die Funktion dieser Funktion besteht darin, die Adresse und den Port in der URL zu analysieren.
Dann kommt der wichtigste Teil. Die Funktion ngx_http_core_listen() ruft am Ende die Funktion ngx_http_add_listen() auf. Diese Funktion speichert die Listen-Port-Informationen im dynamischen Array ports der Struktur ngx_http_core_main_conf_t.
ngx_http_add_listen()-Funktion
// cf: 配置结构体 // cscf: listen指令所在的server的配置结构体 // lsopt : ngx_http_core_listen()生成的listen option ngx_int_t ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_listen_opt_t *lsopt) { in_port_t p; ngx_uint_t i; struct sockaddr *sa; ngx_http_conf_port_t *port; ngx_http_core_main_conf_t *cmcf; // 获取 ngx_http_core_module模块的main_conf结构体ngx_http_core_main_conf_t cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); // ports字段是一个数组 if (cmcf->ports == null) { cmcf->ports = ngx_array_create(cf->temp_pool, 2, sizeof(ngx_http_conf_port_t)); if (cmcf->ports == null) { return ngx_error; } } sa = &lsopt->sockaddr.sockaddr; p = ngx_inet_get_port(sa); port = cmcf->ports->elts; for (i = 0; i < cmcf->ports->nelts; i++) { if (p != port[i].port || sa->sa_family != port[i].family) { continue; } /* a port is already in the port list */ return ngx_http_add_addresses(cf, cscf, &port[i], lsopt); } /* add a port to the port list */ port = ngx_array_push(cmcf->ports); if (port == null) { return ngx_error; } port->family = sa->sa_family; port->port = p; port->addrs.elts = null; return ngx_http_add_address(cf, cscf, port, lsopt); }
Diese Funktion speichert die Portnummerninformationen im Portfeld der ngx_http_core_main_conf_t-Struktur.
Das obige ist der detaillierte Inhalt vonSo verwenden Sie den Listen-Befehl in Nginx. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!