【面試】完全理解 TCP 及面試常問

這個問題真的是爛大街了,可是真正問起來有不少細節的東西須要注意,被騰訊面試官問的我開始懷疑人生了。html

計算機網絡體系結構

在介紹 TCP/IP 以前須要簡單介紹計算機網絡體系結構,固然這個也是面試中常常會問到的。git

總的來講體系結構的劃分有三種:github

  1. 五層協議
  • 應用層

爲特定應用程序提供數據傳輸服務,例如 HTTP、SMTP、FTP、DNS 等,數據單位爲報文(位於應用層的信息分組)面試

  • 運輸層

提供的是進程間的通用數據傳輸服務,在應用程序端點之間傳送應用層報文。包括兩種協議:傳輸控制協議 TCP,提供面向鏈接、可靠的數據傳輸服務,數據單位爲報文段(運輸層分組);用戶數據報協議 UDP,提供無鏈接、盡最大努力的數據傳輸服務,數據單位爲用戶數據報。TCP 主要提供完整性服務,UDP 主要提供及時性服務。bash

  • 網絡層

主機間提供數據傳輸服務,運輸層協議是爲主機中的進程提供數據傳輸服務。網絡層把運輸層傳遞下來的報文段或者用戶數據報封裝成分組。服務器

  • 數據鏈路層

網絡層針對的仍是主機之間的數據傳輸,而主機之間能夠有鏈路,鏈路層就是爲相同鏈路的主機提供服務。數據鏈路層將網絡層傳下來的分組封裝成幀cookie

  • 物理層

考慮的是怎樣在傳輸媒體上傳輸數據比特流,而不是指具體的傳輸媒體。物理層的做用是儘量屏蔽傳輸媒體和通訊手段的差別,使數據鏈路層感受不到這些差別。網絡

  1. OSI

相比於五層協議多了表示層和會話層,用途以下:併發

  • 表示層:數據壓縮、加密以及數據描述,這使得應用程序沒必要擔憂在各臺主機中數據內部格式不一樣的問題
  • 會話層:創建及管理會話
  1. TCP/IP

只有四層,至關於五層協議中數據鏈路層和物理層合併爲網絡接口層。tcp

TCP/IP

TCP 特性

  • TCP 是一種面向鏈接的、可靠的字節流服務
  • 在一個 TCP 鏈接中,僅有兩方進行通訊,廣播和多播不能用於 TCP
  • TCP 使用校驗和,確認和重傳機制來保證可靠傳輸
  • TCP 給數據分節進行排序,並使用累積確認保證數據的順序不變和非重複
  • TCP 使用滑動窗口機制來實現流量控制,經過動態改變窗口的大小進行擁塞控制

注意: TCP 並不能保證數據必定會被接收方收到,由於這是不可能的,總會出現數據的丟失,只不過 TCP 可以保證的是傳送的數據能夠獲得確認,就是說即便沒有到達,能夠有重傳機制來保證,若是到達了還有確認機制來保證數據傳輸的正確性。所以準確的說 TCP 也不是 100% 可靠的協議,所能提供的是數據的可靠遞送或故障的可靠通知。

三次握手與四次揮手

下面爲 TCP 狀態碼列表,以 S 指代服務器,C 指代客戶端,S&C 表示二者,S/C 表示二者之一:

LISTEN S

服務器等待從任意遠程TCP端口的鏈接請求。偵聽狀態。

SYN-SENT C

客戶在發送鏈接請求後等待匹配的鏈接請求。經過connect()函數向服務器發出一個同步(SYNC)信號後進入此狀態。

SYN-RECEIVED S

服務器已經收到併發送同步(SYNC)信號以後等待確認(ACK)請求。

ESTABLISHED S&C

服務器與客戶的鏈接已經打開,收到的數據能夠發送給用戶。數據傳輸步驟的正常狀況。此時鏈接兩端是平等的。這稱做全鏈接。

FIN-WAIT-1 S&C

(服務器或客戶)主動關閉端調用close()函數發出FIN請求包,表示本方的數據發送所有結束,等待TCP鏈接另外一端的ACK確認包或FIN&ACK請求包。

FIN-WAIT-2 S&C

主動關閉端在FIN-WAIT-1狀態下收到ACK確認包,進入等待遠程TCP的鏈接終止請求的半關閉狀態。這時能夠接收數據,但再也不發送數據。

CLOSE-WAIT S&C

被動關閉端接到FIN後,就發出ACK以迴應FIN請求,並進入等待本地用戶的鏈接終止請求的半關閉狀態。這時能夠發送數據,但再也不接收數據。

CLOSING S&C

在發出FIN後,又收到對方發來的FIN後,進入等待對方對己方的鏈接終止(FIN)的確認(ACK)的狀態。少見。

LAST-ACK S&C

被動關閉端所有數據發送完成以後,向主動關閉端發送FIN,進入等待確認包的狀態。

TIME-WAIT S/C

主動關閉端接收到FIN後,就發送ACK包,等待足夠時間以確保被動關閉端收到了終止請求的確認包。【按照RFC 793,一個鏈接能夠在TIME-WAIT保證最大四分鐘,即最大分段壽命(maximum segment lifetime)的2倍】

CLOSED S&C

徹底沒有鏈接。

  1. 三次握手

三次握手協議指的是在發送數據的準備階段,服務器端和客戶端之間須要進行三次交互,詳細過程以下:

用三報文握手創建 TCP 鏈接

  • A 向 B 發送請求報文,發送包含一個 SYN 包,以及一個 seq 號,初始化爲 x
  • B 接收到鏈接請求報文,若是贊成鏈接,就會向 A 發送確認報文,包括 SYN = 1,ACK = 1,確認號爲 x + 1,而也會選擇一個隨機的序號 y
  • A 收到 B 的確認報文之後,還要向 B 發出確認,確認號爲 y + 1,序號爲 x + 1,B 收到之後就簡歷鏈接

三次握手緣由:

第三次握手是爲了防止失效的鏈接請求到達服務器,讓服務器錯誤打開鏈接。客戶端發送的鏈接請求若是在網絡中滯留,那麼就會隔很長一段時間才能收到服務器端的鏈接確認。而對於客戶端來講存在超時重傳機制,就是在超過一個重傳時間尚未收到確認的話,就會從新請求鏈接,可是第一次發送的滯留的鏈接請求還會到達服務器,若是不進行三次握手,那麼服務器就會打開兩個鏈接,若是有三次握手客戶端會忽略服務器以後發送的對滯留鏈接請求的鏈接確認,不進行第三次握手,所以就不會再次打開鏈接。

這裏可能涉及到 SYN 攻擊

  • 什麼是 SYN 攻擊?

在三次握手過程當中,服務器發送 SYN-ACK 以後,收到客戶端的 ACK 以前的 TCP 鏈接稱爲半鏈接(half-open connect)。此時服務器處於 SYN_RCVD 狀態。當收到 ACK 後,服務器才能轉入 ESTABLISHED 狀態。

SYN 攻擊指的是,攻擊客戶端在短期內僞造大量不存在的 IP 地址,向服務器不斷地發送SYN包,服務器回覆確認包,並等待客戶的確認。因爲源地址是不存在的,服務器須要不斷的重發直至超時,這些僞造 SYN 包將長時間佔用未鏈接隊列,正常的 SYN 請求被丟棄,致使目標系統運行緩慢,嚴重者會引發網絡堵塞甚至系統癱瘓。

SYN 攻擊是一種典型的 DoS/DDoS 攻擊。

  • 如何檢測

檢測 SYN 攻擊很是的方便,當你在服務器上看到大量的半鏈接狀態時,特別是源IP地址是隨機的,基本上能夠判定這是一次SYN攻擊。在 Linux/Unix 上可使用系統自帶的 netstats 命令來檢測 SYN 攻擊。

netstat -n -p TCP | grep SYN_RECV
複製代碼
  • 如何防護

SYN攻擊不能徹底被阻止,除非將TCP協議從新設計。咱們所作的是儘量的減輕SYN攻擊的危害,常見的防護 SYN 攻擊的方法有以下幾種:

縮短超時(SYN Timeout)時間、增長最大半鏈接數、過濾網關防禦、SYN cookies技術

  1. 四次揮手

創建一個鏈接須要三次握手,而終止一個鏈接要通過四次握手,這是由TCP的半關閉(half-close)形成的,詳細過程以下:

TCP 四次揮手示意圖

  • A 發送鏈接釋放報文,FIN = 1
  • B 收到以後發出確認,此時 TCP 處於半關閉狀態,就是說 B 能向 A 發送數據可是 A 不能向 B 發送數據,這時候 B 會進入 CLOSE-WAIT 狀態,並會將未傳輸完畢的數據繼續傳送給客戶端。
  • 當 B 數據傳輸完成之後,會發送鏈接釋放報文,FIN = 1,
  • A 收到以後會發出確認,並進入 TIME-WAIT 狀態,等待 2MSL(最大報文存活時間)後釋放鏈接,B 在收到 A 的確認以後會釋放鏈接

TIME-WAIT

客戶端收到服務端鏈接釋放 FIN = 1 之後,不是直接 CLOSED,還須要等待一個時間段 2MSL,這麼作有兩個緣由:

  • 確保最後一個確認報文可以到達,若是 B 沒有收到 A 發送來的確認報文,那麼就會從新發送鏈接釋放請求報文,A 等待一段時間就是爲了防止這種狀況的發生。
  • 等待一段時間是爲了讓本鏈接持續時間內所產生的全部報文都從網絡中小時,使得下一個新的鏈接不會出現舊的鏈接請求報文

參考資料

TCP三次握手及四次揮手詳細圖解

TCP 協議

傳輸控制協議 維基百科

TCP 百度百科

CS-Notes TCP 的三次握手

相關文章
相關標籤/搜索