一、問題
TCP協議之如何保證傳輸的可靠性?我們先看下TCP的頭部圖片和TCP頭部的字段
/*TCP頭定義,共20個字節*/
typedef struct _TCP_HEADER
{
short m_sSourPort; // 源端口號16bit
short m_sDestPort; // 目的端口號16bit
unsigned int m_uiSequNum; // 序列號32bit
unsigned int m_uiAcknowledgeNum; // 確認號32bit
short m_sHeaderLenAndFlag; // 前4位:TCP頭長度;中6位:保留;後6位:標誌位
short m_sWindowSize; // 窗口大小16bit
short m_sCheckSum; // 檢驗和16bit
short m_surgentPointer; // 緊急數據偏移量16bit
} __attribute__((packed))TCP_HEADER, *PTCP_HEADER;
二、 保證可靠性的手段
1)、校驗和(只要協議的包頭裏面有校驗和都支持:比如TCP協議 UDP協議 IP協議)
校驗和:發送的數據段都當做一個16位的整數,將這些整數加起來。並且前面的進位不能丟棄,補在後面,最後取反,得到校驗和。
收方比對校驗和與發送方不一致,那麼數據一定傳輸有誤。但是如果接收方比對校驗和與發送方一致,數據不一定傳輸成功。
2)、確認號與序列號(TCP協議包頭裏面分別是32位,序列號去掉服務端收到的重複數據)
序列號:TCP傳輸時將每個字節的數據都進行了編號,這就是序列號(通過序列號可以去重)
確認應答:TCP傳輸的過程中,每次接收方收到數據後,都會對傳輸方進行確認應答。也就是發送ACK報文。這個ACK報文當中帶有對應的確認序列號,告訴發送方,接收到了哪些數據,下一次的數據從哪裏發。
序列號的作用不僅僅是應答的作用,有了序列號能夠將接收到的數據根據序列號排序,並且去掉重複序列號的數據。這也是TCP傳輸可靠性的保證之一
3)、超時重傳
(1)、發送數據過程中爲什麼沒有客戶端沒有收到服務端返回的ACK的數據包
發送方發送一部分數據後,都會等待接收方發送的ACK報文,但是這時候發送方沒有收到ACK的數據包是怎麼回事?
- 數據在傳輸過程中由於網絡原因等直接全體丟包,接收方根本沒有接收到(發送服務端中途丟包)
- 收方接收到了響應的數據,但是發送的ACK報文響應卻由於網絡原因丟包了 (服務端收到包,返回客戶端丟包)
(2) 、重傳機制
TCP在解決這個問題的時候引入了一個新的機制,叫做超時重傳機制:就是發送方在發送完數據後等待一個時間,時間到達沒有接收到ACK報文,那麼對剛纔發送的數據進行重新發送。
如果是剛纔第一個原因,接收方收到二次重發的數據後,便進行ACK應答。
如果是剛纔第二個原因,接收方發現接收的數據已存在(判斷存在的根據就是序列號,所以上面說序列號還有去除重複數據的作用),那麼直接丟棄,仍舊發送ACK應答
(3)、重傳時間間隔
在Linux中(BSD Unix和Windows下也是這樣)超時以500ms爲一個單位進行控制,每次判定超時重發的超時時間都是500ms的整數倍。重發一次後,仍未響應,那麼等待2*500ms的時間後,再次重傳。等待4*500ms的時間繼續重傳。以一個指數的形式增長。累計到一定的重傳次數,TCP就認爲網絡或者對端出現異常,強制關閉連接。
4)、連接管理
就是三次握手與四次揮手的過程,可以看我的這篇博客 TCP之三次握手和四次揮手過程
5)、流量控制
我們知道實現流量控制是基於滑動窗口來實現的,請看我的這篇滑動窗口的博客 TCP之滑動窗口
6)、擁塞控制
TCP傳輸的過程中,發送端開始發送數據的時候,如果剛開始就發送大量的數據,那麼就可能造成一些問題。網絡可能在開始的時候就很擁堵,如果給網絡中在扔出大量數據,那麼這個擁堵就會加劇。擁堵的加劇就會產生大量的丟包,就對大量的超時重傳,嚴重影響傳輸。
所以TCP引入了慢啓動的機制,在開始發送數據時,先發送少量的數據探路。探清當前的網絡狀態如何,再決定多大的速度進行傳輸。這時候就引入一個叫做擁塞窗口的概念。發送剛開始定義擁塞窗口爲 1,每次收到ACK應答,擁塞窗口加 1。在發送數據之前,首先將擁塞窗口與接收端反饋的窗口大小比對,取較小的值作爲實際發送的窗口。
擁塞窗口的增長是指數級別的。慢啓動的機制只是說明在開始的時候發送的少,發送的慢,但是增長的速度是非常快的。爲了控制擁塞窗口的增長,不能使擁塞窗口單純的加倍,設置一個擁塞窗口的閾值,當擁塞窗口大小超過閾值時,不能再按照指數來增長,而是線性的增長。在慢啓動開始的時候,慢啓動的閾值等於窗口的最大值,一旦造成網絡擁塞,發生超時重傳時,慢啓動的閾值會爲原來的一半(這裏的原來指的是發生網絡擁塞時擁塞窗口的大小),同時擁塞窗口重置爲 1。
擁塞控制是TCP在傳輸時儘可能快的將數據傳輸,並且避免擁塞造成的一系列問題。是可靠性的保證,同時也是維護了傳輸的高效性。
部分類容參考了博客:https://blog.csdn.net/liuchenxia8/article/details/80428157