TCP/IP協議詳解-18章TCP連接的建立與終止讀書筆記part1

TCP連接的建立與終止-讀書筆記part1

  • TCP連接的中止與建立 Part1
    • 引言
      • TCP建立的連接,其實就是在發送和接收的兩端各自維繫的一個連接的狀態。在這個基礎上進行重傳等可靠性保證的處理。與UDP作對比,UDP是無連接的。
    • 連接的建立與終止
      • 使用tcpdump觀察 telnet一個服務器上的某個服務時的報文交互。
      • 3次握手
        • 解釋協議頭部中的一些字段,比如SYN,ACK,包序號,以及應答序號。
        • 初始序號選擇的依憑,ISN,隨時間而變化,可以看作是一個32位或者64位的計數器
      • 4次揮手
        • TCP是一個全雙工的協議,故而允許半關閉。故而是在接收端和發送端分別發送FIN,進行關閉的,同時需要對端應答ACK,確認關閉完成,雙端狀態同步。
        • 發送FIN,即意味着我不會繼續從這一端往這個連接中寫東西了。
    • 連接建立的超時
      • 即異常情況,服務器無響應的狀態下連接超時,書中用服務器斷電模擬了連接建立超時的場景。
      • TCP的SYN會延長間隔時間發送,第一次爲5.5s -6s 之間,第二次爲24秒,最終BSD,即伯克利系統的實現將建立連接完成的最長時間限制爲75s,否則就認爲連接建立失敗,拋出錯誤。
      • 第一次超時時間的不確定是因爲TCP軟件採用的定時器機制,以500ms爲單位,網絡協議棧試圖建立第一個TCP連接時會設置一個6s的定時器,故而相當於會有12次的count計數,第一次設置後的減1 是隨機的。
      • 但是發送SYN的時間不一定是嚴格的間隔500ms的整數倍,因爲在500ms超時後,這會觸發中斷,但這可能是這個時間的其中一箇中斷,系統也可能在處理其他中斷,然後才能調度到這個TCP連接的定時中斷。
    • 最大報文長度(MSS)
      • 這裏注意區分MTU和MSS的概念,MTU是指在數據鏈路層的一個最大分片的大小,這個應該是由二層協議,以及二層協議對應的網卡等物理設施來決定(網卡的操作由協議規定)。
        • 分片
          • 在網絡協議棧中的流程是,在IP層在接收到包後,判斷它所要交付的數據包所在的路由的網卡,網卡所在的數據鏈路環境的二層協議類型,以及在網卡上設定的MTU,來選擇是否對IP層接收到的數據包進行分片。分片後加上MAC層,或者其他二層協議頭部,才能夠正常交付,但這個分片,會在下一個路由器(三層)上被整合,整合完成後又重複上述的動作。(可以想見這個流程需要很大的開銷)
          • 所以一般期望是 IP層要發送的數據包,是小於這整條傳輸線路上的最小的MTU,這樣的話,即使到了最小的MTU這一個環節,數據包也不需要進行分片操作,故而可以不需要在任何一箇中間路由器上進行分片的重組,這點又需要用到MTU探測的技術。
        • 而上面的IP層發送數據包的值,是由TCP層傳遞給IP層的數據包大小決定的,故而將這個值定義爲MSS,即max segment size。
        • 一般意義上MSS的值在小於鏈路上的最小MTU的前提下,越大越好。
    • TCP的半關閉
      • 因爲TCP的連接是全雙工,在實現上允許一端關閉,但仍然允許另一端繼續發送的情況,從用戶態的層面來說,是系統調用 close和shutdown的區分。
        • 如果調用shutdown,對端如果在recv,會接收到一個文件結束符,即從這個socket中已經不會再讀到數據了,但是還可以接收數據。
        • 如果調用close,主動關閉的一端也是發送FIN包,等待對方的ACK包。但是對端發送的FIN包,也是需要等到對方應用層執行close後,纔會在協議棧觸發。但是因對端應用層的行爲是不可預知的,如果長期不發送FIN包,則主動關閉端會長期停留在 FIN_WAIT_2的狀態,而close的目的是使得該socket關閉,故而許多協議棧的實現中會設置定時器,如果超過一定的空閒時間(10min左右),TCP連接仍然將進入到close狀態。但是注意這其實與協議的規範是違背的。
        • 對於shutdown存在的必要性(題外話,這也是我覺得西方一些技術書籍和教學上更優的地方,不只說是什麼,而更多強調爲什麼),介紹了一個 rsh命令的例子,要在對端的機子上遠程執行某個命令時,需要傳輸一部分內容作爲對端程序的標準輸入,在要傳輸的參數部分結束時,調用shutdown可以發送一個文件結束符,對端接收到後可以瞭解到輸入已完成,就可以執行後續的處理,否則就要以其他的技術來通知到對端(比如規定結束分隔符,或者建立另外一條信令的通路)。因爲是在對端的機子上執行,要把處理結果返回給客戶端,故而要保持這一端仍然能夠接收,故而使用半關閉。
    • TCP的狀態遷移圖
      • TCP的連接中一個涉及到11種狀態,在一次的TCP連接中,客戶端和服務端都必然會是處於這11種狀態的其中一種。
      • 這11種狀態可以大致劃分爲5個小類。
        • 第一類是起始狀態,也是結束狀態,即CLOSE狀態。
        • 第二類是準備建立連接,或者連接建立過程中的狀態,包括了 LISTEN狀態(服務器端的被動打開狀態),SYN_SENT狀態(客戶端發送了SYN,建立連接的過程中),SYN_RCVD狀態(服務器端在接收到客戶端的SYN後,回覆消息,進入等待連接建立的狀態,等待三次握手的最後一個數據包到達)
        • 第三類是 連接建立狀態,ESTABLISHED,即此時允許雙工的TCP數據包傳送的狀態
        • 第四類是 主動關閉連接狀態,即服務端或者客戶端任意一端的應用程序調用 close,關閉socket,如下的四種狀態都只會由主動發起關閉的那一方經歷,FIN_WAIT_1狀態(發送了FIN包之後,等待接收對方的ACK,確認發送端的流關閉),FIN_WAIT_2狀態(在接收到FIN包的ACK後,進入到等待來自對端的FIN包的狀態),TIME_WAIT狀態(接收到了對端的FIN包,發送了四次揮手中的最後一個包之後,進入等待狀態,防止最後一個包在鏈路中丟失,而等待進行重傳,如果丟失,對方會認爲之前的FIN包沒有發出來,會重發FIN包),另外還有一個是CLOSING狀態(這個狀態可以認爲是一種特殊情況,因爲作爲主動方先發出FIN之後,到對方收到FIN,這之間是存在一定的窗口期的,也就是時間差,此時對方也可能調用了close 調用希望關閉socket,也發出了FIN包,進入了FIN_WAIT1的狀態,此時回覆ACK即可,不再需要進入到FIN_WAIT_2的狀態再等待接收FIN包了,因爲已經接收到了,後續只要接收到對方對於我們發出的FIN包的ACK,即可進入TIME_WAIT狀態,當然,這裏還是要考慮我們在收到FIN包之後,發出的ACK包丟失的情況,對端可能會重發FIN包)
        • 第五類與第四類對應,是被動關閉連接狀態,CLOSE_WAIT狀態(在收到對方的FIN包之後,回覆對方ACK,此時實際進入了半關閉的狀態,在用戶態下的表現,其實應該是recv函數返回0,但我仍然可以往fd裏面寫內容到對端,因爲對端仍然是開放接收的,故而如果應用程序不主動調用close的話,其實TCP連接是不會被關閉的,對方會一直處於 FIN_WAIT_2的狀態),LAST_ACK狀態(被動關閉端的應用程序也調用close關閉後,被動關閉端發送FIN包,等待主動關閉端返回的ACK,用於最終進入到初始狀態)
      • 2MSL等待狀態在這裏用了非常多的筆墨來描述
        • 2MSL是主動關閉端在進入到TIME_WAIT狀態後的最長等待時間,這裏MSL的定義本身就是一個經驗值,因爲數據包在互聯網中的生存時間,只依賴於IP層的TTL字段做限制,但TTL限制的是跳數,而不是定時器,MSL只是作爲一個經驗值而存在一般爲30s。。這裏的時間是考慮到極端情況,首先是最後一個ACK丟失的最差情況是在網絡中生存了MSL時間後,才被丟棄;另一方面在被動關閉端,在發送最後一個FIN,並等待ACK的時候,對端必然也會有一個超時時間(這裏我只作爲猜測,應該也是2MSL,相當於發送的FIN到達的最長時間,和返回ACK到達的最長時間,主動關閉端協議棧的處理,並響應ACK的時間爲us級別,應該可以忽略不計),在前面最後一個ACK丟失的最差情況下,被動發送端會重發FIN包,而這個FIN包,最遲的到達時間也就是MSL。故而重發的FIN包,到達的最晚時間應該是2MSL。(這裏我認爲忽略了重發的FIN包,丟失需要重傳的情況,但這種情況應該是被認爲微乎其微故而忽略不計了吧)
        • 關於2MSL這裏討論了一個最爲重要的限制,就是TCP連接在2MSL等待時間內是不可再使用的,更確切的說是四元組不可用。但很多實現使用了更強的限制,使得四元組中的本地的端口不可使用。這對於客戶端來說一般沒有影響,因爲客戶端基本使用隨機端口來訪問服務器,但對於服務器端來說,這就意味着在關閉服務端程序之後,在2MSL的時間內,無法再bind該端口,會返回 Address already in use的問題。一般的實現都提供了 SO_RESUSEADDR來繞過這個選項,即可以允許再綁定這個端口,但是注意 對應的四元組仍然是處於 2MSL狀態的,即關閉後,從相同的客戶端ip的相同端口,請求建立TCP連接,是無法成功的。但是對於來自其他ip的相同或者不同端口,只要四元組中有信息不同,就是可以建立連接的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章