1. 程式人生 > >監聽socket初始化

監聽socket初始化

主要在倆塊內容中用到socket的初始化部分,第一塊是在ngx_http_core_srv函式中,在最後設定預設的監聽套介面時有把監聽socket新增進去,第二塊是在ngx_http_block的最後,把配置檔案的socket新增進去

1.結構資訊:
一個port可以對應多個addr,可有多個server監聽同一個addr:port,所以在addr中比較重要的幾個成員如下:
default_server,該埠預設的server
servers:所有在該埠下監聽的server
hash:server name為key,ngx_http_core_srv_conf_t為value的雜湊表
2.解析配置檔案,獲取監聽socket資訊
用於設定監聽socket的指令有倆個,server_name和listen,前者用於設定每個server的虛擬主機名,後者用於設定socket資訊,
1》前者對應的函式為ngx_http_core_server_name,它的作用是將server_name指定的虛擬主機名字新增到ngx_http_core_srv_conf_t中的server_names陣列中,其實他就相當於一個域名的存在
ps:server_name的配置舉例:
server_name jb51.net;比如

http://jb51.net的請求就會轉發到該主機
server_name jb51.net www.jb51.net;http://www.jb51.net
server_name *.jb51.net;設定該主機處理所有來自jb51.net的子域名,比如www.jb51.net,blog.jb51.net等
2》socket對應得函式是ngx_http_core_listen函式
該函式負責解析listen指令配置項的socket配置資訊,並且儲存這些值,在函式的最後呼叫ngx_http_add_listen函式新增監聽socket資訊
cscf->listen=1
//一旦採用了listen指令就代表要使用相應的配置資訊,如果他為0的話,那麼就要在Ngx_http_core_srv函式中配置預設的監聽資訊

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) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
“%s in \”%V\” of the \”listen\” directive”,
u.err, &u.url);
}

return NGX_CONF_ERROR;  

}
//解析listen指令的url,ip和埠號資訊
初始化ngx_http_listen_opt_t結構體,它裡面儲存著一些基本的socket選項,比如常見的recbuf,sndbuf,backlog,而後呼叫ngx_sock_ntop把二進位制的地址轉化為文字格式存入ngx_http_listen_opt_t結構體。
最後呼叫ngx_http_add_listen函式新增監聽socket資訊
ngx_http_add_listen的實現:
a.如果ports為NULL(不為空,就是說已經解析了一個listern),則為ngx_http_core_module的ngx_http_core_main_conf_t.ports分配ngx_http_conf_port
b.通過lsopt獲取埠資訊賦值給變數p
c.這段程式碼是遍歷ports陣列,檢視新新增的埠資訊是否已經存在,如果該埠資訊存在則呼叫ngx_http_add_addresses函式在對應的埠結構上新增地址資訊。否則,在prots陣列中新增一個元素,並初始化,
d.查詢port->addrs陣列中是否已經添加了該ip,如果是,則呼叫ngx_http_add_server把對應得ngx_http_core_srv_conf_t配置新增到ngx_http_conf_addr_t的servers陣列中。
- 若沒找到該IP,呼叫ngx_http_add_address把IP初始化到ngx_http_conf_addr_t結構,新增到port的addrs陣列中。
並且設定default_server,往往是第一個監聽該addr:port的是它的預設server,最後同樣呼叫nginx_http_add_server新增server塊的配置資訊
3》函式ngx_http_block函式中呼叫ngx_http_optimize_servers函式完成ngx_listening_t初始化,下面看一下這個函式的實現。
a.先呼叫ngx_http_server_names初始化ngx_http_conf_addr_t中的三個雜湊表
b.呼叫ngx_http_init_listening初始化ngx_cycle_t中的ngx_listening_t結構體
b.1呼叫ngx_http_add_listening函式往ngx_cycle_t的listenings陣列中新增監聽socket
ngx_http_add_listening函式的實現:
b.11:ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
//建立ngx_listening_t結構體,並且把它新增到listening陣列中,並且設定該ngx_listening_t結構體中的一些主要的成員資訊
b.12:// 設定監聽socket的handler,在監聽到新的連線時呼叫,即ngx_event_accept中。
ls->handler = ngx_http_init_connection;
b.2:呼叫ngx_http_add_addrs函式初始化ngx_listening_t中的servers成員,在處理請求時進行匹配並且賦值給request成員

4》接下來會在ngx_init_cycle函式中呼叫ngx_open_listening_sockets和ngx_configure_listening_sockets完成監聽套介面的開啟和配置
5》接下來就會在ngx_event_process_init函式(ngx_event_core_moduel的process_init回撥函式,在建立完worker程序後呼叫)中將這些監聽socket新增到事件迴圈中

綜上所述,其實主要的流程就是讀取配置檔案,設定好埠,地址,server這三個資料的關係,而後開啟套介面就可以