這個問題真的是爛大街了,可是真正問起來有不少細節的東西須要注意,被騰訊面試官問的我開始懷疑人生了。html
在介紹 TCP/IP 以前須要簡單介紹計算機網絡體系結構,固然這個也是面試中常常會問到的。git
總的來講體系結構的劃分有三種:github
爲特定應用程序提供數據傳輸服務,例如 HTTP、SMTP、FTP、DNS 等,數據單位爲報文(位於應用層的信息分組)面試
提供的是進程間的通用數據傳輸服務,在應用程序端點之間傳送應用層報文。包括兩種協議:傳輸控制協議 TCP,提供面向鏈接、可靠的數據傳輸服務,數據單位爲報文段(運輸層分組);用戶數據報協議 UDP,提供無鏈接、盡最大努力的數據傳輸服務,數據單位爲用戶數據報。TCP 主要提供完整性服務,UDP 主要提供及時性服務。bash
爲主機間提供數據傳輸服務,運輸層協議是爲主機中的進程提供數據傳輸服務。網絡層把運輸層傳遞下來的報文段或者用戶數據報封裝成分組。服務器
網絡層針對的仍是主機之間的數據傳輸,而主機之間能夠有鏈路,鏈路層就是爲相同鏈路的主機提供服務。數據鏈路層將網絡層傳下來的分組封裝成幀cookie
考慮的是怎樣在傳輸媒體上傳輸數據比特流,而不是指具體的傳輸媒體。物理層的做用是儘量屏蔽傳輸媒體和通訊手段的差別,使數據鏈路層感受不到這些差別。網絡
相比於五層協議多了表示層和會話層,用途以下:併發
只有四層,至關於五層協議中數據鏈路層和物理層合併爲網絡接口層。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
徹底沒有鏈接。
三次握手協議指的是在發送數據的準備階段,服務器端和客戶端之間須要進行三次交互,詳細過程以下:
三次握手緣由:
第三次握手是爲了防止失效的鏈接請求到達服務器,讓服務器錯誤打開鏈接。客戶端發送的鏈接請求若是在網絡中滯留,那麼就會隔很長一段時間才能收到服務器端的鏈接確認。而對於客戶端來講存在超時重傳機制,就是在超過一個重傳時間尚未收到確認的話,就會從新請求鏈接,可是第一次發送的滯留的鏈接請求還會到達服務器,若是不進行三次握手,那麼服務器就會打開兩個鏈接,若是有三次握手客戶端會忽略服務器以後發送的對滯留鏈接請求的鏈接確認,不進行第三次握手,所以就不會再次打開鏈接。
這裏可能涉及到 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技術
創建一個鏈接須要三次握手,而終止一個鏈接要通過四次握手,這是由TCP的半關閉(half-close)形成的,詳細過程以下:
TIME-WAIT
客戶端收到服務端鏈接釋放 FIN = 1 之後,不是直接 CLOSED,還須要等待一個時間段 2MSL,這麼作有兩個緣由: