網絡編程 socket programming 學習筆記 (一)

三次握手

TCP 三次握手 ??

三次握手涉及的核心函數(shù)調用

Server::socket, bind, listen
Client::socket, connect

便于理解的一些解釋

關于三次握手, 幾句話解釋清楚
1.信道不安全 保證通信需要一來一回
2.客戶端的來回和服務端的來回 共四次 這是最多四次
3.客戶端的回和服務端的來合并成一個,就是那個SYN k 和 ACK j+1
4.這樣就是三次握手

為什么需要三次握手,不是四次?
tcp 的連接需要確保雙方收和發(fā)消息的能力都是正常的。
客戶端第一次發(fā)送握手 SYN 消息 j 到服務端, 服務端收到握手 SYN 消息 j 后把自己 的握手消息 SYN k 和 握手應答 ACK j+1 一并發(fā)送給客戶端, 這是第二次握手,
當客戶端收到服務端送來的第二次握手消息后,客戶端可以確認“服務端的收發(fā)能力都OK,客戶端的收發(fā)能力也OK”,
但是服務端只能確認“客戶端的發(fā)送OK,服務端的接受OK”,
所以還需要第三次握手, 客戶端收到服務端的第二次握手消息后,發(fā)起第三次ACK k+1 ,服務端收到第三次消息后,就能夠確定“服務端的發(fā)送OK, 客戶端的接收OK”,
至此,客戶端和服務的都能夠確認自己和對方的收發(fā)能力OK, tcp 連接建立完成。

四次揮手

流程概述

假設 發(fā)起端 主機A,接收端 主機B

  1. A 發(fā)送 FIN 報文 m , 進入FIN_WAIT_1
  2. B 回復 ACK 報文 m + 1 ,進入 CLOSE_WAIT 狀態(tài)
  3. A 收到 ACK m + 1 , 進入FIN_WAIT_2
  4. 同時,B 通過read 調用獲得 EOF,并將此結果通知應用程序進行主動關閉操作,發(fā)送 FIN 報文 n
  5. ?A 回復 ACK n + 1 ,進入 TIME_WAIT
  6. B 進入 CLOSED

通常在 TIME_WAIT 停留持續(xù)時間是固定的,是最長分節(jié)生命期 MSL(maximum segment lifetime)的兩倍,一般稱之為 2MSL。和大多數(shù) BSD 派生的系統(tǒng)一樣,Linux 系統(tǒng)里有一個硬編碼的字段,名稱為TCP_TIMEWAIT_LEN,其值為 60 秒。也就是說,Linux 系統(tǒng)停留在 TIME_WAIT 的時間為固定的 60 秒。

四次揮手 ??

只有發(fā)起連接終止的一方會進入 TIME_WAIT 狀態(tài),現(xiàn)在我們來思考一下 TIME_WAIT 的作用。
為什么不直接進入 CLOSED 狀態(tài),而要停留在 TIME_WAIT 這個狀態(tài)?

  1. 這樣做是為了確保最后的 ACK 能讓被動關閉方接收,從而幫助其正常關閉。
    舉個例子:以防一些情況下TCP 報文傳輸會出錯,需要重傳,如果ACK 傳輸失敗,那么FIN 報文會被對端再次發(fā)出,若沒有維護 TIME_WAIT 狀態(tài),直接進入CLOSED 狀態(tài),就失去了當前狀態(tài)的上下文,只能回復RST 報文,從而導致被動關閉方出現(xiàn)錯誤。

  2. 防止延時的報文‘遲到’, 此時舊連接已經不存在,但是恰巧有四元組相同的新連接,這個時候報文會被誤發(fā),對TCP 通信產生影響。所以,按照TCP 設計的規(guī)范,經過2MSL 的時間,舊報文就會被丟棄,從而解決上述這個問題。

2MSL 的時間是從主機 1 接收到 FIN 后發(fā)送 ACK 開始計時的;如果在 TIME_WAIT 時間內,因為主機 1 的 ACK 沒有傳輸?shù)街鳈C 2,主機 1 又接收到了主機 2 重發(fā)的 FIN 報文,那么 2MSL 時間將重新計時。道理很簡單,因為 2MSL 的時間,目的是為了讓舊連接的所有報文都能自然消亡,現(xiàn)在主機 1 重新發(fā)送了 ACK 報文,自然需要重新計時,以便防止這個 ACK 報文對新可能的連接化身造成干擾。

TIME_WAIT 的壞處

  1. 內存資源占用, 這個問題幾乎可以忽略

  2. 對端口資源的占用, 一個 TCP 連接至少消耗一個本地端口。要知道,端口資源也是有限的,一般可以開啟的端口為 32768~61000 ,也可以通過net.ipv4.ip_local_port_range 指定,如果 TIME_WAIT 狀態(tài)過多,會導致無法創(chuàng)建新連接。

如何優(yōu)化 TIME_WAIT ?

  1. net.ipv4.tcp_max_tw_buckets 默認為18000 , 這個值的含義是,當系統(tǒng)中處于 TIME_WAIT 的連接一旦超過這個值時,系統(tǒng)就會將所有 TIME_WAIT 連接狀態(tài)重置,并打印出警告信息。不過這個方法過于暴力,治標不治本,帶來的問題遠比解決的問題多,不推薦使用。
  1. 調低 TCP_TIMEWAIT_LEN,重新編譯系統(tǒng),需要一些內核方面的知識,操作起來有一定的困難。

  2. 設置 SO_LINGER ,比較危險,暫不詳細闡述

  3. net.ipv4.tcp_tw_reuse
    那么 Linux 有沒有提供更安全的選擇呢?
    就是net.ipv4.tcp_tw_reuse選項。
    Linux 系統(tǒng)對于net.ipv4.tcp_tw_reuse的解釋如下:

Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0.It should not be changed without advice/request of technical experts.

這段話的大意是從協(xié)議角度理解如果是安全可控的,可以復用處于 TIME_WAIT 的套接字為新的連接所用。
那么什么是協(xié)議角度理解的安全可控呢?
主要有兩點:

  1. 只適用于連接發(fā)起方(C/S 模型中的客戶端);
  2. 對應的 TIME_WAIT 狀態(tài)的連接創(chuàng)建時間超過 1 秒才可以被復用。

使用這個選項,還有一個前提,需要打開對 TCP 時間戳的支持,即net.ipv4.tcp_timestamps=1(默認即為 1)。

要知道,TCP 協(xié)議也在與時俱進,RFC 1323 中實現(xiàn)了 TCP 拓展規(guī)范,以便保證 TCP 的高可用,并引入了新的 TCP 選項,兩個 4 字節(jié)的時間戳字段,用于記錄 TCP 發(fā)送方的當前時間戳和從對端接收到的最新時間戳。由于引入了時間戳,我們在前面提到的 2MSL 問題就不復存在了,因為重復的數(shù)據(jù)包會因為時間戳過期被自然丟棄。

總結

  • TIME_WAIT 的引入是為了讓 TCP 報文得以自然消失,同時為了讓被動關閉方能夠正常關閉;
  • 不要試圖使用SO_LINGER設置套接字選項,跳過 TIME_WAIT;
  • 現(xiàn)代 Linux 系統(tǒng)引入了更安全可控的方案,可以幫助我們盡可能地復用 TIME_WAIT 狀態(tài)的連接。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1、TCP狀態(tài)linux查看tcp的狀態(tài)命令:1)、netstat -nat 查看TCP各個狀態(tài)的數(shù)量2)、lso...
    北辰青閱讀 9,714評論 0 11
  • 一、網絡各個協(xié)議:TCP/IP、SOCKET、HTTP等 網絡七層由下往上分別為物理層、數(shù)據(jù)鏈路層、網絡層、傳輸層...
    荒漠現(xiàn)甘泉閱讀 475評論 0 0
  • 一、TCP/IP模型與OSI模型的聯(lián)系 二、TCP、UDP協(xié)議的區(qū)別 UDP在傳送數(shù)據(jù)之前不需要先建立連接,遠地主...
    晨微雨夢宿雨飛閱讀 505評論 0 0
  • 三次握手和四次揮手本身并不復雜,但卻可以從很多角度理解這兩個過程,本文僅取一個視點解讀,如有其它看法歡迎留言交流。...
    杰倫哎呦哎呦閱讀 972評論 0 7
  • 從讀大學開始,我就沒打算畢業(yè)后回到家鄉(xiāng)工作,原因倒是有好些。可能因為工作的城市離家鄉(xiāng)并不是很遠,想家了隨時可以回去...
    無邪居閱讀 3,451評論 0 0

友情鏈接更多精彩內容