Heim > Betrieb und Instandhaltung > Nginx > So verwenden Sie den Listen-Befehl in Nginx

So verwenden Sie den Listen-Befehl in Nginx

WBOY
Freigeben: 2023-05-14 18:37:14
nach vorne
2112 Leute haben es durchsucht

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]];
Nach dem Login kopieren

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
Nach dem Login kopieren

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);
}
Nach dem Login kopieren

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 == &#39;*&#39;) {
 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;
}
Nach dem Login kopieren

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 
}
Nach dem Login kopieren

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;
}
Nach dem Login kopieren

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);
}
Nach dem Login kopieren

Diese Funktion speichert die Portnummerninformationen im Portfeld der ngx_http_core_main_conf_t-Struktur.

So verwenden Sie den Listen-Befehl in Nginx

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!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage