關於 TCP 的十四個問題

  1. TCP 是什麼?

  2. TCP 是如何建立(三次握手)?

  3. 爲什麼要三次握手?

  4. TCP 是如何終止的(四次揮手)?

  5. 爲什麼要四次揮手?

  6. 爲什麼四次揮手中的第四次需要等待 2MSL?

  7. 一次 http 請求,誰會先斷開 TCP 連接?什麼情況下客戶端先斷,什麼情況下服務端先斷?

  8. 一個 TCP 連接可以對應幾個 HTTP 請求?

  9. 一個 TCP 連接中可以同時發多個 HTTP 請求嗎?

  10. 爲什麼有時候刷新頁面不需要重新建立 SSL 連接?

  11. 瀏覽器對同一 Host 建立 TCP 連接的數量有沒有限制?

  12. 如何區分 HTTP/1.X 還是 HTTP/2.X 的請求?

  13. 瀏覽器需要加載有幾十張圖片的網頁時,那麼這些圖片是以什麼方式、什麼順序、建立了多少連接、使用什麼協議被下載下來的呢?

  14. 經典的面試題,URL 在瀏覽器輸入到頁面展現的過程中發生了什麼?

各位童鞋,繼續往下看之前,小二建議先在內心中回答一下這十四道問題,然後帶着疑惑,有目的的閱讀,效果會更好喲🎨

01

TCP 是什麼?

在搞清 TCP 是什麼之前,我們需先要了解下 TCP/IP 網路模型。

TCP/IP 是互聯網相關的各類協議族的總稱,比如:TCP,UDP,IP,FTP,HTTP,ICMP,SMTP 等都屬於 TCP/IP 族內的協議。

TCP/IP 模型是互聯網的基礎,它是一系列網絡協議的總稱。這些協議可以劃分爲四層,分別爲鏈路層、網絡層、傳輸層和應用層。

圖中可以看到 TCP 與 UDP 都是屬於傳輸層。

TCP(Transmission Control Protocol,傳輸控制協議)是爲了在不可靠的互聯網絡上提供可靠的端到端字節流而專門設計的一個傳輸協議。TCP 是面向連接的、可靠的流協議。流就是指不間斷的數據結構,你可以把它想象成排水管中的水流。

UDP(User Datagram Protocol,用戶數據報協議)是一種無需建立連接就可以發送封裝的 IP 數據包的方法。

TCP 的面向連接的,雖然說網絡的不安全不穩定特性決定了三次握手也不能保證連接的可靠和穩定性,但 TCP 的三次握手還是在很大程度上保證了連接的可靠性;而 UDP 不是面向連接的,UDP 傳送數據前並不與對方建立連接,對接收到的數據也不發送確認信號,發送端不知道數據是否會正確接收,當然就不用重發,所以說 UDP 是無連接的、不可靠的一種數據傳輸協議,因其不必進行收發數據確認的特點,UDP 的開銷更小傳輸速率更高、實時性更好。

02

TCP 是如何建立(三次握手)?

TCP 是面向連接的,無論哪一方向另一方發送數據之前,都必須先在雙方之間建立一條連接。在 TCP/IP 協議中,TCP 協議提供可靠的連接服務,連接是通過三次握手進行初始化的。三次握手的目的是同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息。

**第一次握手:**建立連接。客戶端發送連接請求報文段,將 SYN 位置爲 1,Seq 爲 X;然後,客戶端進入 SYN_SEND 狀態,等待服務器的確認;

**第二次握手:**服務端收到客戶端 SYN 報文,對 SYN 報文進行確認,設置 ACK 爲 X+1,同時要發送自己的 SYN 信息,Seq 爲 Y,服務器端將上述所有信息放到一個報文段(即 SYN+ACK 報文段)中,一併發送給客戶端,此時服務器進入 SYN_RECV 狀態;

**第三次握手:**客戶端收到服務器的 SYN+ACK 報文段,然後將 ACK 設置爲 Y+1,向服務器發送 ACK 報文段,這個報文段發送完畢以後,客戶端和服務器端都進入 ESTABLISHED 狀態,完成 TCP 三次握手。

03

爲什麼要三次握手?

爲了防止因爲一些原因造成失效的報文傳送到服務器,而導致的問題。

例如在網絡情況不佳的情況下,客戶端發的連接請求報文在傳輸中滯留了一段時間纔到達服務端,此時當前這個請求報文已失效,但服務端收到這個失效的請求報文後,如果不採用三次握手確認,就會誤認爲是客戶端再次發出的一個新的連接請求,服務端建立連接,然後服務端就一直等待客戶端發送數據,但是客戶端根本就不知道連接已建立,服務端當然收不到消息,資源被浪費掉。而採用三次握手機制,當失效報文傳到服務端時,服務端向客戶端發送確認報文段,同意建立連接,這個時候客戶端因爲沒有發起過建立連接的請求,因此不會給服務端回確認消息,服務端收不到確認消息,就知道客戶端沒有要求建立連接。

04

TCP 是如何終止(四次揮手)?

當數據傳輸結束後,就需要斷開 TCP 連接,關於 TCP 連接斷開,這裏就提起 TCP 的四次揮手了。

**第一次揮手:**主動方(客戶端或服務端),設置 Seq,向被動方發 FIN 報文段,主動方進入 FIN_WAIT_1 狀態,主動方說:再見,我要關閉了。

**第二次揮手:**被動方收到主動方 FIN 報文段,向主動方回一個 ACK 報文段,確認序號爲 Seq+1,主動方進入 FIN_WAIT_2 狀態,被動方說:我知道了。

**第三次揮手:**被動方向主動方發送 FIN 報文段,請求關閉連接,同時被動方進入 LAST_ACK 狀態,被動方說:再見,我要關閉了。

**第四次揮手:**主動方收到被動方的 FIN 報文段,向被動方發送 ACK 報文段,然後主動方進入 TIME_WAIT 狀態,被動方收到主動方 ACK 報文段,就關閉連接,此時主動方等待 2MSL 後沒收到回覆後,主動方纔關閉連接,主動方說:我知道了,等待 2MSL 後關閉了連接。

05

爲什麼要四次揮手?

TCP 協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。主動方第一次揮手即告訴被動方,我沒數據需要發送了,被動方收到主動方無數據發送信息之後,這個時候被動方還是可以發送數據給主動方的,被動方進行第二次揮手發送 ACK 報文給主動方,等待被動方處理完自己的事情,發送 FIN 報文段時,即第三次揮手,告訴主動方我也沒數據需要發送了,這個時候主動方收到 FIN 報文段就會發送 ACK,即第四揮手,告訴被動方你可以關閉了。

06

爲什麼四次揮手中的第四次需要等待 2MSL?

MSL(Maximum Segment Lifetime) 報文最長存活時間。

原因一:防止舊連接的數據包

當 TCP 連接關閉之前,有一段報文被網絡延遲了,這是有相同端口的新的 TCP 連接被建立時,延遲的報文抵達了客戶端,這個時候客戶端是有可能會接收這個過期的報文,這樣就會造成數據錯亂的問題。

原因二:保證連接正確關閉

當主動方四次揮手的最後一個 ACK 報文段在網絡中丟失了,此時如果主動方不等待 2MSL,則直接進入 ClOSE 狀態,那麼被動方會一直處於 LAST_ACK 狀態,這時主動方又重新發起 TCP 連接時,被動方會直接將過程終止,連接無法建立。如果主動方等待 2MSL,則會有兩個情況,一是被動方收到四次揮手的最後一個 ACK 報文段,被動方正常關閉連接;二是被動方沒有收到四次握手的最後一個 ACK 報文段時,主動方則會重發 FIN 關閉連接報文並等待新的 ACK 報文。

07

一次 http 請求,誰會先斷開 TCP 連接?什麼情況下客戶端先斷?什麼情況下服務先斷?

對於 http1.0 協議來說,如果響應頭中有 content-length,代表客戶端知道 body 的長度,客戶端接收的時候按照這個長度接收,接收完畢後,客戶端會主動調用 close 進入四次揮手

而對於 http1.1 協議來說,如果響應頭中的 Transfer-encoding 爲 chunked 傳輸,則表示 body 是流式輸出,body 會被分成多塊,且每塊會標識長度,或者響應頭中有 content-length,這兩種情況在數據接收完畢後,客戶端都會主動調用 close 進入四次揮手,如果非 chunked 並沒有 content-length,則客戶端接收數據,直到服務端主動斷開連接

以上兩種情況,都是基於沒有建立持久連接的情況下,當請求頭中 connection 爲 keep-alive,服務端在輸出完 body 會開啓長連接,如果 connection 爲 close,則表示客戶端需要關閉長連接,根據協議 http1.0 默認爲 close,http1.1 默認爲 keep-alive.

最後在不考慮 keep-alive 的情況下,http1.0,帶 content-length,body 長度可知,客戶端會主動調用 close 進入四次揮手,不帶 content-length,body 長度不可知,則客戶端一直接受數據,直到服務端主動斷開。http1.1,帶 content-length,body 長度可知,客戶端主動斷開;帶 Transfer-encoding:chunked ,body 會被分成多個塊,且每塊會標識長度,客戶端主動斷開; 不帶 Transfer-encoding:chunked 且不帶 content-length,則客戶端一直接受數據,直到服務端主動斷開

即:如果能夠有辦法知道服務器傳來的長度,都是客戶端首先斷開;如果不知道就一直接收數據,直到服務端斷開。

08

一個 TCP 連接可以對應幾個 HTTP 請求?

如果是持久連接的話,一個 TCP 是可以發送很多個 HTTP 的請求。

09

一個 TCP 連接中可以同時發多個請求嗎?

http1.1 下開啓持久連接,單個 TCP 連接在同一時刻也只能處理一個請求,one by one 必須要等上一個請求結束才能開始下一個,http1.1 爲了解決這個問題提出了 Pipelining 管道化方案,但是這個功能在瀏覽器中是默認關閉的,其要求收到請求的服務器必須按照請求收到的順序發送響應,然而客戶端無法根據響應結果來判斷對應哪個請求。

10

爲什麼有時候刷新頁面先不需要重新建立 SSL 連接?

如果是持久連接的話,是可以複用 TCP 連接的,刷新頁面也不需要重新建立 SSL 連接。

11

瀏覽器對同一 Host 建立 TCP 連接的數量有沒有限制?

是有限制的,如果不限制,在大量併發請求下,服務器扛不住。各大瀏覽器對於數量的不一樣的大致是在 2-10 之間。

12

如何區分 HTTP/1.X 還是 HTTP/2.X 的請求?

13

瀏覽器需要加載有幾十張圖片的網頁時,那麼這些圖片是以什麼方式、什麼順序、建立了多少連接、使用什麼協議被下載下來的呢?

如果圖片都是 https 連接且在同一域名下,那麼瀏覽器在 SSL 握手後會和服務器商量能不能用 http2,能用就使用 Multiplexing 多路複用功能在這個連接上進行多路傳輸,如果用不了,那就看瀏覽器能在一個 host 下建立多少個 TCP,通過建立多個 TCP 連接來傳輸數據,如果大部分連接都被佔用,那就只能等待了。

14

URL 在瀏覽器輸入到頁面展現的過程中發生了什麼?

引用文章:

https://juejin.cn/post/6844903490595061767#heading-0

https://www.cnblogs.com/web21/p/6397525.html

https://www.sohu.com/a/451071921_453160

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8HZrMcAbq8nfJH6Ga6SW3A