一、什麼是網路層?#
TCP 網路分層一般分為四層,當然也有說法是五層
- 應用層(HTTP):封裝資料包
- 傳輸層(TCP):增加 TCP 頭部,包含端口號等資訊
- 網路層(IP):增加 IP 頭部,包含 IP 地址等資訊
- 網路介面層(ARP):增加以太網頭部,包含 MAC 地址等資訊
網路分層的優點:
- 各層獨立:限制了依賴關係的範圍,各層之間使用標準化的介面,各層不需要知道上下層是如何工作的,增加或者修改一個應用層協議不會影響傳輸層協議;
- 靈活性:比如路由器不需要應用層和傳輸層,分層以後路由器就可以只用加載更少的幾個協議層
- 易於測試和維護:提高了可測試性,可以獨立的測試特定層,某一層有了更好的實現可以整體替換掉;
- 能促進標準化:各層職能清晰,方便標準化;
二、TCP 的三次握手?為什麼不是兩次或者四次?#
- 客戶端向服務端發送 SYN,seq = x;
- 服務端向客戶端發送 SYN,seq = y, ACK = x+1;
- 客戶端向服務端發送 ACK = y+1;
兩次不行因為如果只做兩次無法確定服務端的接收能力;
兩次握手後建立連接,有可能導致由於時延產生的多次連接建立,導致資源浪費;
四次的話沒必要,會導致資源浪費。
三、TCP 的四次揮手?為什麼不能是三次?#
- 客戶端向服務端發送 FIN,seq = x+2,ACK = y+1;
- 服務端向客戶端發送 ACK = x+3;
- 服務端發送完剩餘數據後,再向客戶端發送 FIN,seq = y+1;
- 客戶端向服務端發送 ACK = y+2;
三次不行,會導致服務端的 ACK 和 FIN 將延遲發送,如果延遲時間過長,客戶端將再次重發斷開請求,導致資源浪費。
四、為什麼 SYN/FIN 不包含數據卻要消耗一個序列號?#
凡是需要對端確認的,一定消耗 TCP 報文的序列號;
五、什麼是半連接隊列?什麼是 SYN Flood 攻擊?#
客戶端大量偽造 IP 發送 SYN 包,服務端回復的 ACK+SYN 去到了一個(未知)的 IP 地址,勢必會造成服務端大量的連接處於 SYN_RCVD 狀態,而伺服器的半連接隊列大小也是有限的,如果半連接隊列滿,也會出現無法處理正常請求的情況。
六、TCP 快速打開的原理?#
TCP 快速打開(TCP Fast Open,TFO)
TFO 是在原來 TCP 協議上的擴展協議,它的主要原理就在發送第一個 SYN 包的時候就開始傳數據了,不過他要求當前客戶端之前已經完成過正常的三次握手。
快速打開分為兩個階段:請求 Fast Open Cookie 和 真正開始 TCP Fast Open
TCP Fast Open 的優勢
可以利用握手去除一個往返的 RTT 和防止 SYN-Flood 之類的攻擊
七、TCP 報文中的時間戳有什麼用?#
TCP Timestamps Option 由四部分構成:類別、長度、發送方時間戳、回顯時間戳
第一用於計算 RTT,第二防止序列號的回環問題,即使使用的序列號相同,也可以通過時間戳來對不同的包進行區分。
八、TCP 的超時重傳時間是如何計算的?#
超時重傳時間:Retransmission TimeOut, 簡稱 RTO
經典解決方法
適用於 RTT 較小的情況,SRTT (smoothed round trip time)。
利用最新一次的 RTT 對 SRTT 時間進行更新
SRTT = α × SRTT + (1-α)× RTT
九、TCP 流量控制?#
把發送的數據放到發送緩衝區,把接收的數據放到接收緩衝區。通過實際接收緩衝區的大小,控制發送端的發送。
接收端會告知客戶端自己接收窗口,也就是接收緩衝區中空閒的部分。
發送端的數據包的狀態:
- 已發送且已確認
- 已發送未確認的
- 未發送但接收端可以接受的(接收端有空間接受)
- 未發送且不可以發送(接收端沒空間接受)
發送端速度較慢:存在大量待發送的字節;
發送端速度較快:存在大量待確認的字節;
十、TCP 的 keep-alive 原理?#
定時發送探測包來探測連接的對端是否存活,但是 keepalive 默認設置的時間過長,7200s 沒有實際意義,一般在應用層做心跳機制。
那什麼是心跳機制?
定時向服務端發送消息,能響應服務端的消息
長連接業務場景
- 遊戲
- 即時通訊
在沒有心跳包機制的情況下,網路若掉線,對方不可知;
如果客戶端掉線,服務端不知道,還維持連接,就是額外的無效系統開銷。
為什麼需要心跳包:
- 在 NAT、防火牆網路中裝設備,保存信道記錄;
- 及時發現對方網路斷開,以便及時採取措施;
如何實現心跳包
- TCP 層面的心跳包,只能夠驗證網路連接是否異常;
- 應用層層面的心跳包,驗證服務接口是否異常;
為什麼不採用 TCP 層面?
應用層的連接如果成功,那麼 TCP 所在的傳輸層必定成功。
十一、TCP 中的端口號?#
- 源端口:本地端口
- 目標端口:伺服器端口
最大 65536 個,所以是 0-65535
以下是一些常見的端口號:
- 21:FTP(檔案傳輸協議)端口,用於檔案上傳和下載。
- 22:SSH(安全外殼協議)端口,用於安全遠程登錄和執行命令。
- 25:SMTP(簡單郵件傳輸協議)端口,用於電子郵件傳輸。
- 80:HTTP(超文本傳輸協議)端口,用於 Web 瀏覽器訪問網站。
- 110:POP3(郵局協議版本 3)端口,用於電子郵件客戶端接收郵件。
- 143:IMAP(互聯網消息訪問協議)端口,用於電子郵件客戶端接收郵件。
- 443:HTTPS(超文本傳輸安全協議)端口,用於安全的 Web 瀏覽器訪問網站。
- 3306:MySQL 數據庫端口,用於數據存儲和檢索。
- 3389:Microsoft 遠程桌面端口,用於遠程管理和控制計算機。
這只是一小部分常用的端口號,實際上有許多其他端口號可以用於各種不同的通信協議和應用程序。
十二、TCP 場景問題#
問題 1
AB 兩個主機之間建立了一個 TCP 連接,A 主機發給 B 主機兩個 TCP 報文,大小分別是 500 和 300,第一個報文的序列號是 200,那麼 B 主機接收兩個報文後,返回的確認號是多少?
500+300+200 = 1000
問題 2
收到 IP 數據包解析後,如何知道應該投遞到上層中的哪個協議(是 TCP 還是 UDP)?
IP 報文頭中有協議字段,TCP6,UDP17
問題 3
TCP 提供了一種字節流服務,而收發雙方都不保持記錄的邊界,應用程序應該如何提供他們自己的記錄標識呢?
應用程序使用自己約定的規則來標識消息的邊界,比如有一些使用回車+換行(“\r\n”),比如 Redis 的通信協議;
十三、TCP 和 UDP 的區別?#
TCP 是一個面向連接的、可靠的、基於字節流的傳輸層協議;
UDP 是一個面向無連接的傳輸層協議;
-
面向連接:指的是客戶端和服務端的連接,在通信前通過三次握手建立連接;
-
可靠性:
- TCP 有狀態:TCP 會精確記錄那些數據發送了,哪些數據已被接收,那些數據未被接收,並且保證數據包按序到達,不允許差錯;
- TCP 可控制:如果遇到丟包或者網路不佳,TCP 會根據具體情況自行調整,控制自己的發送速度或者重發。
十四、Telnet 和 netstat 的用法#
- 檢查遠端端口是否打開,其語法:telnet [ip] [port]
- 主要用於查詢網路情況,如: netstat -ano
十五、Tcpdump 和 wireshark#
用於抓包,例如可以查看三次握手和四次揮手等