nginx模块开发—HTTP初始化之listen
1、知识百科
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解。与网络有关的配置命令主要有两个:listen和sever_name。listen命令设置nginx监听地址,对于IP协议,这个地址就是address和port,对于UNIX域套接字协议,这个地址就是path,一条listen指令只能指定一个address或者port,address也可以是主机名,比如:
listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000;
listen [::]:8000;
listen [fe80::1];
listen unix:/var/run/nginx.sock;
server_name指令列出虚拟主机的所有主机名,如server_name example.com *.example.com www.example.*,用空格分割。
2、数据结构
ngx_http_conf_port_t(ngx_http_core_listen入口)
typedef struct {
ngx_int_t family;
in_port_t port;
ngx_array_t addrs; /* array of ngx_http_conf_addr_t */
} ngx_http_conf_port_t;
ngx_http_conf_addr_t
typedef struct {
ngx_http_listen_opt_t opt;
ngx_hash_t hash;
ngx_hash_wildcard_t *wc_head;
ngx_hash_wildcard_t *wc_tail;
ngx_http_core_srv_conf_t *default_server;
ngx_array_t servers; /* array of ngx_http_core_srv_conf_t */
} ngx_http_conf_addr_t;
ngx_http_core_srv_conf_t
typedef struct {
/* array of the ngx_http_server_name_t, "server_name" directive */
ngx_array_t server_names;
/* server ctx */
ngx_http_conf_ctx_t *ctx;
ngx_str_t server_name;
size_t connection_pool_size;
size_t request_pool_size;
size_t client_header_buffer_size;
ngx_bufs_t large_client_header_buffers;
ngx_msec_t client_header_timeout;
ngx_flag_t ignore_invalid_headers;
ngx_flag_t merge_slashes;
ngx_flag_t underscores_in_headers;
unsigned listen:1;
ngx_http_core_loc_conf_t **named_locations;
} ngx_http_core_srv_conf_t;
ngx_http_listen_opt_t(重要)
typedef struct {
union {
struct sockaddr sockaddr;
struct sockaddr_in sockaddr_in;
u_char sockaddr_da
} u;
socklen_t socklen;
unsigned set:1; // bind/backlog/…
unsigned default_server:1; // default_server
unsigned bind:1; // bind/backlog/…
unsigned wildcard:1;
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
#if (NGX_HTTP_SPDY)
unsigned spdy:1; // spdy
#endif
unsigned so_keepalive:2;
unsigned proxy_protocol:1; // proxy_protocol
int backlog; // backlog
int rcvbuf; // rcvbuf
int sndbuf; // sndbuf
。。。
u_char addr[NGX_SOCKADDR_STRLEN + 1]; // 0.0.0.0:8000
} ngx_http_listen_opt_t;
ngx_listening_s(ngx_http_init_connection入口)
struct ngx_listening_s {
ngx_socket_t fd;
struct sockaddr *sockaddr;
socklen_t socklen; /* size of sockaddr */
size_t addr_text_max_len;
ngx_str_t addr_text;
int type;
int backlog;
int rcvbuf;
int sndbuf;
ngx_connection_handler_pt handler;
void *servers; /* array of ngx_http_port_t, for example */
。。。
ngx_listening_t *previous;
ngx_connection_t *connection;
unsigned open:1;
unsigned remain:1;
unsigned ignore:1;
unsigned bound:1; /* already bound */
unsigned inherited:1; /* inherited from previous process */
unsigned nonblocking_accept:1;
unsigned listen:1;
unsigned nonblocking:1;
unsigned shared:1; /* shared between threads or processes */
unsigned addr_ntop:1;
unsigned keepalive:2;
};
ngx_http_port_t
typedef struct {
/* ngx_http_in_addr_t or ngx_http_in6_addr_t */
void *addrs;
ngx_uint_t naddrs;
} ngx_http_port_t;
ngx_http_in_addr_t
typedef struct {
in_addr_t addr;
ngx_http_addr_conf_t conf;
} ngx_http_in_addr_t;
ngx_http_addr_conf_s
struct ngx_http_addr_conf_s {
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *default_server;
ngx_http_virtual_names_t *virtual_names;
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
#if (NGX_HTTP_SPDY)
unsigned spdy:1;
#endif
unsigned proxy_protocol:1;
};
3、源码解析
ngx_http_core_server_name
函数功能:解析server_name指令。
static char *
ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_srv_conf_t *cscf = conf;
u_char ch;
ngx_str_t *value;
ngx_uint_t i;
ngx_http_server_name_t *sn;
value = cf->args->elts;
for (i = 1; i < cf->args->nelts; i++) {
ch = value[i].da
if ((ch == "*" && (value[i].len < 3 || value[i].da
|| (ch == "." && value[i].len < 2))
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"server name "%V" is invalid", &value[i]);
return NGX_CONF_ERROR;
}
if (ngx_strchr(value[i].da
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"server name "%V" has suspicious symbols",
&value[i]);
}
sn = ngx_array_push(&cscf->server_names);
if (sn == NULL) {
return NGX_CONF_ERROR;
}
sn->server = cscf;
if (ngx_strcasecmp(value[i].da
sn->name = cf->cycle->hostname;
} else {
sn->name = value[i];
}
if (value[i].da
ngx_strlow(sn->name.da
continue;
}
。。。
}
return NGX_CONF_OK;
}
ngx_http_core_listen
函数功能:解析listen指令。
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;
//解析listen命令后面的参数,ip:port
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in "%V" of the "listen" directive",
u.err, &u.url);
}
- 上一篇: C语言中指针和数组的几种访问形式
- 下一篇: PHP——文件(创建、写入、上传)