又被鵝廠搞懵了!
時(shí)間:2021-09-03 10:13:03
手機(jī)看文章
掃描二維碼
隨時(shí)隨地手機(jī)看文章
[導(dǎo)讀]大家好,我是小林。昨天收到個(gè)讀者的問題,他在面試鵝廠的時(shí)候,被面試官搞懵了,因?yàn)槊嬖嚬賳柫怂@么一個(gè)網(wǎng)絡(luò)問題:不得不說,鵝廠真的很喜歡問網(wǎng)絡(luò)問題,而且愛問異常情況下的網(wǎng)絡(luò)問題,之前也有篇另外一個(gè)讀者面試鵝廠的網(wǎng)絡(luò)問題:「被鵝廠面怕了!」。我們來看看這位讀者的問題,這個(gè)問題其實(shí)是在...
大家好,我是小林。昨天收到個(gè)讀者的問題,他在面試鵝廠的時(shí)候,被面試官搞懵了,因?yàn)槊嬖嚬賳柫怂@么一個(gè)網(wǎng)絡(luò)問題:不得不說,鵝廠真的很喜歡問網(wǎng)絡(luò)問題,而且愛問異常情況下的網(wǎng)絡(luò)問題,之前也有篇另外一個(gè)讀者面試鵝廠的網(wǎng)絡(luò)問題:「被鵝廠面怕了!」。我們來看看這位讀者的問題,這個(gè)問題其實(shí)是在問:客戶端(主動(dòng)關(guān)閉方)在 TIME_WAIT 狀態(tài)下,如果收到服務(wù)端的數(shù)據(jù)包時(shí),會(huì)怎么處理?這個(gè)問題迷惑性在于,客戶端是使用了 shutdown 函數(shù)關(guān)閉了寫方向,而讀方向并沒有關(guān)閉,也就是說客戶端在揮手過程中,如果收到服務(wù)端的數(shù)據(jù)包,那么應(yīng)用程序在調(diào)用 read 函數(shù)時(shí),是可以讀取到數(shù)據(jù)的。如果問題中的數(shù)據(jù)包沒有被網(wǎng)絡(luò)延遲,在第三次揮手之前被客戶端收到了,那么客戶端就可以在應(yīng)用程序讀取到該數(shù)據(jù)。所以疑惑就在于,數(shù)據(jù)包被延遲了,客戶端在進(jìn)入 TIME_WAIT 狀態(tài)后,收到了服務(wù)端的數(shù)據(jù)包,應(yīng)用程序還能讀取到該數(shù)據(jù)嗎?我先說結(jié)論吧,客戶端進(jìn)入 TIME_WAIT 狀態(tài)后,如果收到了服務(wù)端的數(shù)據(jù)包,客戶端的內(nèi)核會(huì)發(fā)送該數(shù)據(jù)包的 ACK 確認(rèn)報(bào)文,然后丟掉該數(shù)據(jù)包。
我為什么知道呢?因?yàn)槲胰タ戳讼聝?nèi)核的源碼,我在這里也帶大家分析一遍。Linux 內(nèi)核在收到 TCP 報(bào)文后,會(huì)執(zhí)行
「別再摸魚了,再摸魚,我就吃了你!」
我為什么知道呢?因?yàn)槲胰タ戳讼聝?nèi)核的源碼,我在這里也帶大家分析一遍。Linux 內(nèi)核在收到 TCP 報(bào)文后,會(huì)執(zhí)行
tcp_v4_rcv
函數(shù),在該函數(shù)和 TIME_WAIT 狀態(tài)相關(guān)的主要代碼如下所示:該代碼的過程:- 接收到SKb包后,會(huì)調(diào)用__inet_lookup_skb()查找對(duì)應(yīng)的sock結(jié)構(gòu);
- 如果連接的狀態(tài)是 TIME_WAIT,會(huì)跳轉(zhuǎn)到 do_time_wait 處理;
- 由 tcp_timewait_state_process() 函數(shù)來處理 SKB 包,處理后根據(jù)返回值來做相應(yīng)的處理。
- 如果返回值是 TCP_TW_SYN,則說明接收到的是一個(gè)「合法」的SYN包(也就是說這個(gè) SYN 包可以接受),這時(shí)會(huì)首先查找內(nèi)核中是否有對(duì)應(yīng)的監(jiān)聽套接字,如果存在相應(yīng)的監(jiān)聽套接字,則會(huì)釋放TIME_WAIT狀態(tài)的傳輸控制結(jié)構(gòu),跳轉(zhuǎn)到 process 處開始處理,開始建立一個(gè)新的連接。如果沒有找到監(jiān)聽套接字會(huì)執(zhí)行到 TCP_TW_ACK 分支。
- 如果返回值是TCP_TW_ACK,則會(huì)調(diào)用 tcp_v4_timewait_ack() 發(fā)送ACK,然后跳轉(zhuǎn)到 discard_it,丟掉數(shù)據(jù)包。
- 如果返回值是TCP_TW_RST,則會(huì)調(diào)用 tcp_v4_send_reset() 給對(duì)端發(fā)送 RST 包,然后丟掉數(shù)據(jù)包。
- 如果返回值是TCP_TW_SUCCESS,則會(huì)直接丟掉數(shù)據(jù)包。
「別再摸魚了,再摸魚,我就吃了你!」