www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 小林coding
[導(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í)行 tcp_v4_rcv 函數(shù),在該函數(shù)和 TIME_WAIT 狀態(tài)相關(guān)的主要代碼如下所示:該代碼的過程:
  1. 接收到SKb包后,會(huì)調(diào)用__inet_lookup_skb()查找對(duì)應(yīng)的sock結(jié)構(gòu);

  2. 如果連接的狀態(tài)是 TIME_WAIT,會(huì)跳轉(zhuǎn)到 do_time_wait 處理;

  3. 由 tcp_timewait_state_process() 函數(shù)來處理 SKB 包,處理后根據(jù)返回值來做相應(yīng)的處理。

在看 tcp_timewait_state_process() 函數(shù)中的處理之前,需要先看一看不同的返回值會(huì)對(duì)應(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ù)包。

所以,關(guān)鍵的地方就在于,當(dāng)連接在 TIME_WAIT 狀態(tài)時(shí),收到了 TCP 數(shù)據(jù)包,tcp_timewait_state_process() 函數(shù)的返回值是什么。tcp_timewait_state_process() 函數(shù)處理過程非常的多,我這里就不詳細(xì)介紹里面的具體處理了,我這里直接說結(jié)論。主動(dòng)關(guān)閉方在 TIME_WAIT 狀態(tài)下,收到了 TCP 數(shù)據(jù)包的話,tcp_timewait_state_process() 函數(shù)會(huì)返回 TCP_TW_ACK,所以接下來會(huì)調(diào)用 tcp_v4_timewait_ack() 發(fā)送 ACK,然后跳轉(zhuǎn)到 discard_it,丟掉數(shù)據(jù)包。可能有的同學(xué)會(huì)好奇,都要丟棄數(shù)據(jù)包了,為什么還要回 ACK?我覺得可能是避免對(duì)方因?yàn)闆]有收到數(shù)據(jù)包的確認(rèn)報(bào)文,而觸發(fā)超時(shí)重傳包,畢竟已經(jīng)在揮手的最末尾階段了,就安安穩(wěn)穩(wěn)的結(jié)束吧。在 TIME_WAIT 狀態(tài)下,還有個(gè)意思的事情是,當(dāng)收到「合法」的 SYN 包,并且開啟了 sysctl_tcp_tw_reuse 內(nèi)核參數(shù),就會(huì)直接釋放掉 TIME_WAIT 的資源,然后進(jìn)行新建連接的處理。這次就說到這啦,下次見!最后,送大家個(gè)我家兩只貓咪的壁紙,自從我電腦換了這個(gè)壁紙后,看到屏幕的時(shí)候,總感覺他們?cè)谡f:
別再摸魚了,再摸魚,我就吃了你!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉