TCP 5連問,你能抗到第幾輪?

語言: CN / TW / HK

1,TCP3次握手具體過程

2,請聊聊SYN攻擊

3,CLOSE-WAIT 和 TIME-WAIT的作用

4,TCP如何保證可靠性

5,TCP如何進行擁塞控制

答案解析

​ TCP是面向連線的通訊協議,通過三次握手建立連線,通訊完成時要拆除連線,由於TCP是面向連線的所以只能用於端到端的通訊。

​ TCP提供的是一種可靠的資料流服務,採用“帶重傳的肯定確認”技術來實現傳輸的可靠性。TCP還採用一種稱為“滑動視窗”的方式進行流量控制,所謂視窗實際表示接收能力,用以限制傳送方的傳送速度。

​ 如果IP資料包中有已經封好的TCP資料包,那麼IP將把它們向‘上’傳送到TCP層。TCP將包排序並進行錯誤檢查,同時實現虛電路間的連線。TCP資料包中包括序號和確認,所以未按照順序收到的包可以被排序,而損壞的包可以被重傳。

​ TCP將它的資訊送到更高層的應用程式,例如Telnet的服務程式和客戶程式。應用程式輪流將資訊送回TCP層,TCP層便將它們向下傳送到IP層,裝置驅動程式和物理介質,最後到接收方。

​ 面向連線的服務(例如TelnetFTPrlogin、[X Windows](https://baike.baidu.com/item/X Windows)和SMTP)需要高度的可靠性,所以它們使用了TCP。DNS在某些情況下使用TCP(傳送和接收域名資料庫),但使用UDP傳送有關單個主機的資訊。

TCP三次握手

file

為什麼需要三次握手

​ 主機建立連線為什麼需要三次握手?為了防止已經是失效連線突然又重新回到了服務端而產生的錯誤。“比如一個客戶端發出一個連線請求報文雖然沒有丟失,但是由於一些原因在在某個網路節點中長時間滯留,以至於在斷開連線後才到達服務端。這本身就是一個已經失效的報文。但是伺服器誤以為是客戶端的又一個新的請求。假設沒有三次握手那麼只要服務端發出確認連結就建立了。由於客戶端也沒有給服務端發請求,因此也不回覆服務端的確認。但是服務端確認為新的連線開始了,等待客戶端發資料。這樣就容易造成服務端的資源的浪費。採用三次握手可以防止這種情況發生。

​ TCP 提供面向有連線的通訊傳輸。面向有連線是指在資料通訊開始之前先做好兩端之間的準備工作。

​ 所謂三次握手是指建立一個 TCP 連線時需要客戶端和伺服器端總共傳送三個包以確認連線的建立。在socket程式設計中,這一過程由客戶端執行connect來觸發。

第一次握手

​ 客戶端將標誌位SYN置為1,隨機產生一個值seq=J,並將該資料包傳送給伺服器端,客戶端進入SYN_SENT狀態,等待伺服器端確認。

第二次握手

​ 伺服器端收到資料包後由標誌位SYN=1知道客戶端請求建立連線,伺服器端將標誌位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,並將該資料包傳送給客戶端以確認連線請求,伺服器端進入SYN_RCVD狀態。

第三次握手

​ 客戶端收到確認後,檢查ack是否為J+1,ACK是否為1,如果正確則將標誌位ACK置為1,ack=K+1,並將該資料包傳送給伺服器端,伺服器端檢查ack是否為K+1,ACK是否為1,如果正確則連線建立成功,客戶端和伺服器端進入ESTABLISHED狀態,完成三次握手,隨後客戶端與伺服器端之間可以開始傳輸資料了。

TCP的三次握手的漏洞

​ 但是在TCP三次握手中是有一個缺陷的,就是如果我們利用三次握手的缺陷進行攻擊。這個攻擊就是SYN洪泛攻擊。三次握手中有一個第二次握手,服務端向客戶端應道請求,應答請求是需要客戶端IP的,服務端是需要知道客戶端IP的,攻擊者就偽造這個IP,往伺服器端狂傳送第一次握手的內容,當然第一次握手中的客戶端IP地址是偽造的,從而服務端忙於進行第二次握手但是第二次握手當然沒有結果,所以導致伺服器端被拖累,宕機。

​ 當然我們的生活中也有可能有這種例子,一個家境一般的IT男去表白他的女神被拒絕了,理由是他家裡沒礦,IT男為了報復,採用了洪泛攻擊,他請了很多人偽裝成有錢人去表白那位追求礦的女神,讓女生每次想交往時發現表白的人不見了同時還聯絡不上了。

面對這種攻擊,有以下的解決方案,最好的方案是防火牆。

無效連線監視釋放

​ 這種方法不停監視所有的連線,包括三次握手的,還有握手一次的,反正是所有的,當達到一定(與)閾值時拆除這些連線,從而釋放系統資源。這種方法對於所有的連線一視同仁,不管是正常的還是攻擊的,所以這種方式不推薦。

延緩TCB分配方法

​ 一般的做完第一次握手之後,伺服器就需要為該請求分配一個TCB(連線控制資源),通常這個資源需要200多個位元組。延遲TCB的分配,當正常連線建立起來後再分配TCB則可以有效地減輕伺服器資源的消耗。

使用防火牆

​ 防火牆在確認了連線的有效性後,才向內部的伺服器(Listener)發起SYN請求,

TCP四次揮手(斷開連線)

file

​ 四次揮手即終止TCP連線,就是指斷開一個TCP連線時,需要客戶端和服務端總共傳送4個包以確認連線的斷開。在socket程式設計中,這一過程由客戶端或服務端任一方執行close來觸發。

​ 由於TCP連線是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成資料傳送任務後,傳送一個FIN來終止這一方向的連線,收到一個FIN只是意味著這一方向上沒有資料流動了,即不會再收到資料了,但是在這個TCP連線上仍然能夠傳送資料,直到這一方向也傳送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

file

  1. 客戶端程序發出連線釋放報文,並且停止傳送資料。釋放資料報文首部,FIN=1,其序列號為seq=u(等於前面已經傳送過來的資料的最後一個位元組的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即使不攜帶資料,也要消耗一個序號。

  2. 伺服器收到連線釋放報文,發出確認報文,ACK=1,ack=u+1,並且帶上自己的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP伺服器通知高層的應用程序,客戶端向伺服器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有資料要傳送了,但是伺服器若傳送資料,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。

  3. 客戶端收到伺服器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待伺服器傳送連線釋放報文(在這之前還需要接受伺服器傳送的最後的資料)。

  4. 伺服器將最後的資料傳送完畢後,就向客戶端傳送連線釋放報文,FIN=1,ack=u+1,由於在半關閉狀態,伺服器很可能又傳送了一些資料,假定此時的序列號為seq=w,此時,伺服器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。

  5. 客戶端收到伺服器的連線釋放報文後,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連線還沒有釋放,必須經過2∗∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。

​ 伺服器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB後,就結束了這次的TCP連線。可以看到,伺服器結束TCP連線的時間要比客戶端早一些。

為什麼揮手比握手多一次

​ 因為tcp連線是全雙工的,因此每個方向都必須單獨的斷開連線客戶端申請斷開連線,只是不再發送資料,還能接收資料。需要等待服務端將資料傳送完畢後,等待服務端申請斷開連線。

TCP/IP中的資料包

file

​ 每個分層中,都會對所傳送的資料附加一個首部,在這個首部中包含了該層必要的資訊,如傳送的目標地址以及協議相關資訊。通常,為協議提供的資訊為包首部,所要傳送的內容為資料。在下一層的角度看,從上一層收到的包全部都被認為是本層的資料。

​ 網路中傳輸的資料包由兩部分組成:一部分是協議所要用到的首部,另一部分是上一層傳過來的資料。首部的結構由協議的具體規範詳細定義。在資料包的首部,明確標明瞭協議應該如何讀取資料。反過來說,看到首部,也就能夠了解該協議必要的資訊以及所要處理的資料。

應用程式處理

​ 首先應用程式會進行編碼處理,這些編碼相當於 OSI 的表示層功能; 編碼轉化後,郵件不一定馬上被髮送出去,這種何時建立通訊連線何時傳送資料的管理功能,相當於 OSI 的會話層功能。

TCP 模組的處理

​ TCP 根據應用的指示,負責建立連線、傳送資料以及斷開連線。TCP 提供將應用層發來的資料順利傳送至對端的可靠傳輸。為了實現這一功能,需要在應用層資料的前端附加一個 TCP 首部。

IP 模組的處理

​ IP 將 TCP 傳過來的 TCP 首部和 TCP 資料合起來當做自己的資料,並在 TCP 首部的前端加上自己的 IP 首部。IP 包生成後,參考路由控制表決定接受此 IP 包的路由或主機。

網路介面(乙太網驅動)的處理

​ 從 IP 傳過來的 IP 包對於乙太網來說就是資料。給這些資料附加上乙太網首部並進行傳送處理,生成的乙太網資料包將通過物理層傳輸給接收端。

網路介面(乙太網驅動)的處理

​ 主機收到乙太網包後,首先從乙太網包首部找到 MAC 地址判斷是否為傳送給自己的包,若不是則丟棄資料。 如果是傳送給自己的包,則從乙太網包首部中的型別確定資料型別,再傳給相應的模組,如 IP、ARP 等。這裡的例子則是 IP 。

IP 模組的處理

​ IP 模組接收到 資料後也做類似的處理。從包首部中判斷此 IP 地址是否與自己的 IP 地址匹配,如果匹配則根據首部的協議型別將資料傳送給對應的模組,如 TCP、UDP。這裡的例子則是 TCP。 另外嗎,對於有路由器的情況,接收端地址往往不是自己的地址,此時,需要藉助路由控制表,在調查應該送往的主機或路由器之後再進行轉發資料。

TCP 模組的處理

​ 在 TCP 模組中,首先會計算一下校驗和,判斷資料是否被破壞。然後檢查是否在按照序號接收資料。最後檢查埠號,確定具體的應用程式。資料被完整地接收以後,會傳給由埠號識別的應用程式。

應用程式的處理

​ 接收端應用程式會直接接收發送端傳送的資料。通過解析資料,展示相應的內容。

TCP的通訊原理

Socket套接字

file

​ Socket 的原意是“插座”,在計算機通訊領域,socket 被翻譯為“套接字”,它是計算機之間進行通訊的一種約定或一種方式。通過 socket 這種約定,一臺計算機可以接收其他計算機的資料,也可以向其他計算機發送資料。TCP用主機的IP地址加上主機上的埠號作為TCP連線的端點,這種端點就叫做套接字(socket)。

​ 區分不同應用程式程序間的網路通訊和連線,主要有3個引數:通訊的目的IP地址、使用的傳輸層協議(TCP或UDP)和使用的埠號。通過將這3個引數結合起來,與一個“插座”Socket繫結,應用層就可以和傳輸層通過套接字介面,區分來自不同應用程式程序或網路連線的通訊,實現資料傳輸的併發服務。

​ 套接字對是一個定義該連線的兩個端點的四元組:本地IP地址、本地TCP埠號、外地IP地址、外地TCP埠號。套接字對唯一標識一個網路上的每個TCP連線。

TCP緩衝區

file ​ 每個TCP的Socket的核心中都有一個傳送緩衝區和一個接收緩衝區。現在我們假設用write()方法傳送資料,使用 read()方法接收資料。

​ write()並不立即向網路中傳輸資料,而是先將資料寫入緩衝區中,再由TCP協議將資料從緩衝區傳送到目標機器。一旦將資料寫入到緩衝區,函式就可以成功返回,不管它們有沒有到達目標機器,也不管它們何時被髮送到網路,這些都是TCP協議負責的事情。

​ TCP協議獨立於 write()函式,資料有可能剛被寫入緩衝區就傳送到網路,也可能在緩衝區中不斷積壓,多次寫入的資料被一次性發送到網路,這取決於當時的網路情況、當前執行緒是否空閒等諸多因素,不由程式設計師控制。

​ read()也是如此,也從輸入緩衝區中讀取資料,而不是直接從網路中讀取。

總得來說,I/O緩衝區在每個TCP套接字中單獨存在;I/O緩衝區在建立套接字時自動生成;

TCP 的可靠性

file

​ 在 TCP 中,當傳送端的資料到達接收主機時,接收端主機會返回一個已收到訊息的通知。這個訊息叫做確認應答(ACK)。當傳送端將資料發出之後會等待對端的確認應答。如果有確認應答,說明資料已經成功到達對端。反之,則資料丟失的可能性很大。

​ 在一定時間內沒有等待到確認應答,傳送端就可以認為資料已經丟失,並進行重發。由此,即使產生了丟包,仍然能夠保證資料能夠到達對端,實現可靠傳輸。

​ 未收到確認應答並不意味著資料一定丟失。也有可能是資料對方已經收到,只是返回的確認應答在途中丟失。這種情況也會導致傳送端誤以為資料沒有到達目的地而重發資料。

​ 此外,也有可能因為一些其他原因導致確認應答延遲到達,在源主機重發資料以後才到達的情況也屢見不鮮。此時,源主機只要按照機制重發資料即可。

​ 對於目標主機來說,反覆收到相同的資料是不可取的。為了對上層應用提供可靠的傳輸,目標主機必須放棄重複的資料包。為此我們引入了序列號。

​ 序列號是按照順序給傳送資料的每一個位元組(8位位元組)都標上號碼的編號。接收端查詢接收資料 TCP 首部中的序列號和資料的長度,將自己下一步應該接收的序列號作為確認應答返送回去。通過序列號和確認應答號,TCP 能夠識別是否已經接收資料,又能夠判斷是否需要接收,從而實現可靠傳輸。

TCP中的滑動視窗

​ 傳送方和接收方都會維護一個數據幀的序列,這個序列被稱作視窗。傳送方的視窗大小由接收方確認,目的是控制傳送速度,以免接收方的快取不夠大導致溢位,同時控制流量也可以避免網路擁塞。

​ 在TCP 的可靠性的圖中,我們可以看到,傳送方每傳送一個數據接收方就要給傳送方一個ACK對這個資料進行確認。只有接收了這個確認資料以後傳送方才能傳輸下個數據。

​ 存在的問題:如果視窗過小,當傳輸比較大的資料的時候需要不停的對資料進行確認,這個時候就會造成很大的延遲。

​ 如果視窗過大,我們假設傳送方一次傳送100個數據,但接收方只能處理50個數據,這樣每次都只對這50個數據進行確認。傳送方下一次還是傳送100個數據,但接受方還是隻能處理50個數據。這樣就避免了不必要的資料來擁塞我們的鏈路。

​ 因此,我們引入了滑動視窗。滑動視窗通俗來講就是一種流量控制技術。

​ 它本質上是描述接收方的TCP資料報緩衝區大小的資料,傳送方根據這個資料來計算自己最多能傳送多長的資料,如果傳送方收到接收方的視窗大小為0的TCP資料報,那麼傳送方將停止傳送資料,等到接收方傳送視窗大小不為0的資料報的到來。

固定視窗大小的問題

我們可以看下面一張圖來分析一下固定視窗大小有什麼問題。

file ​ 這裡我們可以看到假設視窗的大小是1,也是就每次只能傳送一個數據只有接受方對這個資料進行確認了以後才能傳送第2個數據。我們可以看到傳送方每傳送一個數據接受方就要給傳送方一個ACK對這個資料進行確認。只有接受到了這個確認資料以後傳送方才能傳輸下個數據。

滑動視窗如何工作

​ 這樣我們考慮一下如果說視窗過小,那麼當傳輸比較大的資料的時候需要不停的對資料進行確認,這個時候就會造成很大的延遲。如果說視窗的大小定義的過大。我們假設傳送方一次傳送100個數據。但是接收方只能處理50個數據。這樣每次都會只對這50個數據進行確認。傳送方下一次還是傳送100個數據,但是接受方還是隻能處理50個數據。這樣就避免了不必要的資料來擁塞我們的鏈路。所以我們就引入了滑動視窗機制,視窗的大小並不是固定的而是根據我們之間的鏈路的頻寬的大小,這個時候鏈路是否擁護塞。接受方是否能處理這麼多資料了。

file

​ 首先是第一次傳送資料這個時候的視窗大小是根據鏈路頻寬的大小來決定的。我們假設這個時候視窗的大小是3。這個時候接受方收到資料以後會對資料進行確認告訴傳送方我下次希望手到的是資料是多少。這裡我們看到接收方傳送的ACK=3。這個時候傳送方收到這個資料以後就知道我第一次傳送的3個數據對方只收到了2個。就知道第3個數據對方沒有收到。下次在傳送的時候就從第3個數據開始發。這個時候視窗大小就變成了2 。

file 這個時候傳送方傳送2個數據。

file

​ 看到接收方傳送的ACK是5就表示他下一次希望收到的資料是5,傳送方就知道我剛才傳送的2個數據對方收了這個時候開始傳送第5個數據。

​ 這就是滑動視窗的工作機制,當鏈路變好了或者變差了這個視窗還會發生變話,並不是第一次協商好了以後就永遠不變了。

​ 所以滑動視窗協議,是TCP使用的一種流量控制方法。該協議允許傳送方在停止並等待確認前可以連續傳送多個分組。由於傳送方不必每發一個分組就停下來等待確認,因此該協議可以加速資料的傳輸。

​ 只有在接收視窗向前滑動時(與此同時也傳送了確認),傳送窗口才有可能向前滑動。

​ 收發兩端的視窗按照以上規律不斷地向前滑動,因此這種協議又稱為滑動視窗協議。

本文由傳智教育博學谷教研團隊釋出。

如果本文對您有幫助,歡迎關注點贊;如果您有任何建議也可留言評論私信,您的支援是我堅持創作的動力。

轉載請註明出處!