本節(jié)開始分析lighttpd中處理連接的狀態(tài)機(jī),也就是connections.c文件中的connection_state_machine函數(shù).我們將沿著上一節(jié)中給出的狀態(tài)機(jī)示意圖一步一步往下走,以圖把這個(gè)過程分析清楚.這也是目前為止唯一一個(gè)詳細(xì)進(jìn)行分析的函數(shù),希望這樣可以更加突出這個(gè)函數(shù)的重要性.
一)CON_STATE_REQUEST_START狀態(tài)
這個(gè)狀態(tài)出現(xiàn)在剛剛通過accept函數(shù)接收一個(gè)新的連接時(shí),此時(shí)需要保存一些數(shù)據(jù):
case CON_STATE_REQUEST_START: /* transient, 開始接收請(qǐng)求 */
if (srv->srvconf.log_state_handling) {
log_error_write(srv, __FILE__, __LINE__, "sds",
"state for fd", con->fd, connection_get_state(con->state));
}
// 保存時(shí)間
con->request_start = srv->cur_ts;
con->read_idle_ts = srv->cur_ts;
// 該連接的請(qǐng)求次數(shù)
con->request_count++;
// 每次循環(huán)處理的請(qǐng)求次數(shù)
con->loops_per_request = 0;
// 狀態(tài)改為可讀, 也就是可以接收數(shù)據(jù)
connection_set_state(srv, con, CON_STATE_READ);
/* patch con->conf.is_ssl if the connection is a ssl-socket already */
#ifdef USE_OPENSSL
con->conf.is_ssl = srv_sock->is_ssl;
#endif
break;
需要注意的是這里將connetion中的兩個(gè)字段保存為當(dāng)前時(shí)間,request_start和read_idle_ts, 前者存放的是接收連接的時(shí)間, 后者用于超時(shí)判斷, 在第5節(jié)講解lighttpd中如何處理超時(shí)的時(shí)候提到過,lighttpd設(shè)置了一個(gè)每一秒一次的定時(shí)器, 每次定時(shí)器到時(shí)就依次輪詢所有的連接, 判斷是否超時(shí), 而判斷的依據(jù)就是拿當(dāng)前的時(shí)間 - connection的read_idle_ts字段, 看看是否超時(shí):
// 如果當(dāng)前時(shí)間與read_idle_ts之差大于max_read_idle, 超時(shí)
if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
/* time - out */
connection_set_state(srv, con, CON_STATE_ERROR);
changed = 1;
}
這些該保存的數(shù)據(jù)都保存完畢之后, 狀態(tài)機(jī)進(jìn)入下一個(gè)狀態(tài),CON_STATE_READ, 也就是開始接收數(shù)據(jù), 這是下一節(jié)要講解的內(nèi)容了.