<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          又被鵝廠搞懵了!

          共 1814字,需瀏覽 4分鐘

           ·

          2021-09-03 15:08

          大家好,我是小林。

          昨天收到個讀者的問題,他在面試鵝廠的時候,被面試官搞懵了,因為面試官問了他這么一個網(wǎng)絡問題:
          不得不說,鵝廠真的很喜歡問網(wǎng)絡問題,而且愛問異常情況下的網(wǎng)絡問題,之前也有篇另外一個讀者面試鵝廠的網(wǎng)絡問題:「被鵝廠面怕了!」。
          我們來看看這位讀者的問題,這個問題其實是在問:客戶端(主動關閉方)在 TIME_WAIT 狀態(tài)下,如果收到服務端的數(shù)據(jù)包時,會怎么處理?
          這個問題迷惑性在于,客戶端是使用了 shutdown 函數(shù)關閉了寫方向,而讀方向并沒有關閉,也就是說客戶端在揮手過程中,如果收到服務端的數(shù)據(jù)包,那么應用程序在調(diào)用 read 函數(shù)時,是可以讀取到數(shù)據(jù)的。
          如果問題中的數(shù)據(jù)包沒有被網(wǎng)絡延遲,在第三次揮手之前被客戶端收到了,那么客戶端就可以在應用程序讀取到該數(shù)據(jù)。
          所以疑惑就在于,數(shù)據(jù)包被延遲了,客戶端在進入 TIME_WAIT 狀態(tài)后,收到了服務端的數(shù)據(jù)包,應用程序還能讀取到該數(shù)據(jù)嗎?
          我先說結(jié)論吧,客戶端進入 TIME_WAIT 狀態(tài)后,如果收到了服務端的數(shù)據(jù)包,客戶端的內(nèi)核會發(fā)送該數(shù)據(jù)包的 ACK 確認報文,然后丟掉該數(shù)據(jù)包。

          我為什么知道呢?因為我去看了下內(nèi)核的源碼,我在這里也帶大家分析一遍。
          Linux 內(nèi)核在收到 TCP 報文后,會執(zhí)行 tcp_v4_rcv 函數(shù),在該函數(shù)和 TIME_WAIT 狀態(tài)相關的主要代碼如下所示:
          該代碼的過程:
          1. 接收到SKb包后,會調(diào)用__inet_lookup_skb()查找對應的sock結(jié)構(gòu);

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

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

          在看 tcp_timewait_state_process() 函數(shù)中的處理之前,需要先看一看不同的返回值會對應什么樣的處理:
          • 如果返回值是 TCP_TW_SYN,則說明接收到的是一個「合法」的SYN包(也就是說這個 SYN 包可以接受),這時會首先查找內(nèi)核中是否有對應的監(jiān)聽套接字,如果存在相應的監(jiān)聽套接字,則會釋放TIME_WAIT狀態(tài)的傳輸控制結(jié)構(gòu),跳轉(zhuǎn)到 process 處開始處理,開始建立一個新的連接。如果沒有找到監(jiān)聽套接字會執(zhí)行到 TCP_TW_ACK 分支。

          • 如果返回值是TCP_TW_ACK,則會調(diào)用 tcp_v4_timewait_ack() 發(fā)送ACK,然后跳轉(zhuǎn)到 discard_it,丟掉數(shù)據(jù)包。

          • 如果返回值是TCP_TW_RST,則會調(diào)用 tcp_v4_send_reset() 給對端發(fā)送 RST 包,然后丟掉數(shù)據(jù)包。

          • 如果返回值是TCP_TW_SUCCESS,則會直接丟掉數(shù)據(jù)包。

          所以,關鍵的地方就在于,當連接在 TIME_WAIT 狀態(tài)時,收到了 TCP 數(shù)據(jù)包,tcp_timewait_state_process() 函數(shù)的返回值是什么。
          tcp_timewait_state_process() 函數(shù)處理過程非常的多,我這里就不詳細介紹里面的具體處理了,我這里直接說結(jié)論。
          主動關閉方在 TIME_WAIT 狀態(tài)下,收到了 TCP 數(shù)據(jù)包的話,tcp_timewait_state_process() 函數(shù)會返回 TCP_TW_ACK,所以接下來會調(diào)用 tcp_v4_timewait_ack() 發(fā)送 ACK,然后跳轉(zhuǎn)到 discard_it,丟掉數(shù)據(jù)包。
          可能有的同學會好奇,都要丟棄數(shù)據(jù)包了,為什么還要回 ACK?
          我覺得可能是避免對方因為沒有收到數(shù)據(jù)包的確認報文,而觸發(fā)超時重傳包,畢竟已經(jīng)在揮手的最末尾階段了,就安安穩(wěn)穩(wěn)的結(jié)束吧。
          在 TIME_WAIT 狀態(tài)下,還有個意思的事情是,當收到「合法」的 SYN 包,并且開啟了 sysctl_tcp_tw_reuse 內(nèi)核參數(shù),就會直接釋放掉 TIME_WAIT 的資源,然后進行新建連接的處理。

          這次就說到這啦,下次見!
          最后,送大家個我家兩只貓咪的壁紙,自從我電腦換了這個壁紙后,看到屏幕的時候,總感覺他們在說:
          別再摸魚了,再摸魚,我就吃了你!

          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久热99r视频在线 | 影音先锋成人无码影院 | 日韩一区二区三区黄片 | 国产精品三级毛片 | 粉嫩av懂色av蜜臀av分享 |