1 TCP三次握手、四次揮手
2 TCP滑動窗口機制
image.png
- 客戶端不斷快速發(fā)送數據,服務器接收相對較慢,看下實驗的結果
a. 包175,發(fā)送ACK攜帶WIN = 384,告知客戶端,現(xiàn)在只能接收384個字節(jié)
b. 包176,客戶端果真只發(fā)送了384個字節(jié),Wireshark也比較智能,也宣告TCP Window Full
c. 包177,服務器回復一個ACK,并通告窗口為0,說明接收方已經收到所有數據,并保存到緩沖區(qū),但是這個時候應用程序并沒有接收這些數據,導致緩沖區(qū)沒有更多的空間,故通告窗口為0, 這也就是所謂的零窗口,零窗口期間,發(fā)送方停止發(fā)送數據
d. 客戶端察覺到窗口為0,則不再發(fā)送數據給接收方
e. 包178,接收方發(fā)送一個窗口通告,告知發(fā)送方已經有接收數據的能力了,可以發(fā)送數據包了
f. 包179,收到窗口通告之后,就發(fā)送緩沖區(qū)內的數據了.
3 TCP擁塞控制機制
擁塞控制的算法有:慢開始、擁塞避免、快重傳、快恢復四種。
擁塞的標志:重傳計時器超時、接收到三個重復確認。
控制機制:


快重傳:

面試題:
騰訊面試題
TCP的擁塞控制機制是什么?請簡單說說。
答:我們知道TCP通過一個定時器(timer)采樣了RTT并計算RTO,但是,如果網絡上的延時突然增加,那么,TCP對這個事做出的應對只有重傳數據,然而重傳會導致網絡的負擔更重,于是會導致更大的延遲以及更多的丟包,這就導致了惡性循環(huán),最終形成“網絡風暴” —— TCP的擁塞控制機制就是用于應對這種情況。
首先需要了解一個概念,為了在發(fā)送端調節(jié)所要發(fā)送的數據量,定義了一個“擁塞窗口”(Congestion Window),在發(fā)送數據時,將擁塞窗口的大小與接收端ack的窗口大小做比較,取較小者作為發(fā)送數據量的上限。
擁塞控制主要是四個算法:
1.慢啟動:意思是剛剛加入網絡的連接,一點一點地提速,不要一上來就把路占滿。
連接建好的開始先初始化cwnd = 1,表明可以傳一個MSS大小的數據。
每當收到一個ACK,cwnd++; 呈線性上升
每當過了一個RTT,cwnd = cwnd*2; 呈指數讓升
閾值ssthresh(slow start threshold),是一個上限,當cwnd >= ssthresh時,就會進入“擁塞避免算法”
2.擁塞避免:當擁塞窗口 cwnd 達到一個閾值時,窗口大小不再呈指數上升,而是以線性上升,避免增長過快導致網絡擁塞。
每當收到一個ACK,cwnd = cwnd + 1/cwnd
每當過了一個RTT,cwnd = cwnd + 1
擁塞發(fā)生:當發(fā)生丟包進行數據包重傳時,表示網絡已經擁塞。分兩種情況進行處理:
等到RTO超時,重傳數據包
sshthresh = cwnd /2
cwnd 重置為 1
3.進入慢啟動過程
在收到3個duplicate ACK時就開啟重傳,而不用等到RTO超時
sshthresh = cwnd = cwnd /2
進入快速恢復算法——Fast Recovery
4.快速恢復:至少收到了3個Duplicated Acks,說明網絡也不那么糟糕,可以快速恢復。
cwnd = sshthresh + 3 * MSS (3的意思是確認有3個數據包被收到了)
重傳Duplicated ACKs指定的數據包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就進入了擁塞避免的算法了。
4 socket模型
image.png
套接字的幾個函數對應的TCP操作
image.png
socket
創(chuàng)建套接字,指定要使用的地址簇(ip)和套接字類型/傳輸層協(xié)議(tcp),返回一個套接字描述符,簡稱sockfd,用于在函數調用(connect、read 等)中標識這個套接字。
bind
將一個 本地IP:本地端口 賦值給一個套接字,限定該套接字只接收目的地為指定的本地IP、端口的客戶連接。進程指定。
linsen
僅由 TCP server 調用。當 socket 函數創(chuàng)建了套接字,會假設為主動套接字,也就是將調用 connect 主動發(fā)起連接的套接字。linsen 將一個未連接的套接字轉換成被動套接字,通知內核應該接受指向該套接字的連接請求(被動打開)。此時套接字的狀態(tài)從 CLOSED 轉到 LISTEN。
內核為每個監(jiān)聽套接字維護兩個隊列:
未完成連接隊列,收到了客戶的 SYN,正在等待 TCP 三次握手完成。此時套接字的狀態(tài)為 SYN_RCVD。
已完成連接隊列,已經完成 TCP 三次握手的客戶,這些套接字處于 ESTABLISHED 狀態(tài)。
當收到客戶的SYN,TCP在未完成連接隊列中創(chuàng)建一項新條目,同時繼承監(jiān)聽套接字的參數,然后返回SYS、ACK,這一項一直保留在未完成連接隊列中,直到收到 ACK,或者該項超時。如果三次握手正常完成,該項從未完成連接隊列移到已完成連接隊列的隊尾。
指定 backlog,即兩個隊列長度之和。
image.png
accept
僅由 TCP server 調用,從已完成連接的隊頭獲得一個已完成連接,如果已完成連接的隊列為空,進程被掛起進入睡眠狀態(tài)(假定套接字為默認的阻塞方式),直到隊列中有條目。
接收監(jiān)聽套接字描述符,返回 由內核自動為獲得的已完成連接生成的已連接套接字描述符,以及對應的已連接套接字。
connect
僅由 TCP client 調用,接收 socket 返回的套接字描述符,主動向 TCP server 發(fā)送建立連接的請求(主動打開),觸發(fā)三次握手。調用 connect 之前不一定要調用 bind 綁定本地ip 和 本地端口,這樣,內核會通過數據出口確定源ip,并選定一個臨時端口作為源端口。
- TCP UDP區(qū)別
1、基于連接與無連接;
2、對系統(tǒng)資源的要求(TCP較多,UDP少);
3、UDP程序結構較簡單;
4、流模式與數據報模式 ;
5、TCP保證數據正確性,UDP可能丟包;
6、TCP保證數據順序,UDP不保證。 - Time_Wait中2*msl 為什么
如果TIME_WAIT狀態(tài)保持時間不足夠長,第一個連接就正常終止了。第二個擁有相同五元組的連接出現(xiàn),而第一個連接的重復報文到達,干擾了第二個連接。TCP事先必須防止某個連接的重復報文在連接終止后出現(xiàn),所以讓TIME_WAIT狀態(tài)保持時間足夠長(2MSL),連接相應方向的上的TCP報文要么完全響應完畢,要么被丟棄。建立第二個連接的時候,不會混淆。 - 一個url從輸入到訪問經過了哪些過程
1.DNS 解析:將域名解析成 IP 地址
2.TCP 連接:TCP 三次握手
3.發(fā)送 HTTP 請求
4.服務器處理請求并返回 HTTP 報文
5.瀏覽器解析渲染頁面
6.斷開連接:TCP 四次揮手



