文章目錄
- 流量控制
- 擁塞控制
- 擁塞窗口
- 延遲應答
- 捎帶應答
- 面向字節流
- 粘包問題
- TCP的異常
流量控制
由于接收端處理數據的速度是有限的,如果發送端發的太快,那么接收端的緩沖區就可能會滿。此時如果發送端還發數據,就會出現丟包現象,并且可能出現一系列連鎖反應。
所以TCP支持根據接收端的處理能力去決定發送端的發送速度,這種機制就叫做流量控制
- 接收端會將自己的緩沖區大小,也就是報頭中的窗口大小告知給發送端,發送端根據情況改變發送速度
- 窗口大小越大,說明網絡的吞吐量就越高
擁塞控制
雖然TCP有滑動窗口這個機制可以高效可靠的發送大量數據,但是如果在剛開始的時候就發送了大量的數據就仍然可能出現問題
因此TCP在防止出現擁塞問題上加入了慢啟動機制
顧名思義就是先發送少量的數據區探探路,摸清當前的網絡擁堵情況,再決定應該按照多快的速度去傳輸數據
少量的丟包, TCP僅僅是觸發超時重傳; 大量的丟包, TCP就認為網絡擁塞。
TCP通信開始后, 網絡吞吐量會逐漸上升; 隨著網絡發生擁堵, 吞吐量會立刻下降.
所以擁塞控制, 歸根結底是TCP協議想盡可能快的把數據傳輸給對方, 但是又要避免給網絡造成太大壓力的折中方案
擁塞窗口
此處就又引入一個概念—擁塞窗口
- 在通信開始前,擁塞窗口設為1
- 每收到一個ACK應答時,擁塞窗口加1
- 每次發送數據包時,都將擁塞窗口和報頭中的窗口大小做比較,之后取較小的值作為實際發送的窗口大小
這樣做就可以很符合慢啟動機制,一開始的窗口大小就會呈指數型的增長,到后面就會慢下來呈線性增長,這種就相當于給了一個閾值,沒超過這個值時就可以增長的快一點,一旦超過就慢下來
因此可以將這個閾值一開始啟動時候就設為窗口大小的最大值,每次超過這個值那么TCP就會觸發重發機制,這時候每一次觸發重發都將這個閾值減少一半,同時擁塞窗口置為1
這樣就可以很好的控制住擁塞
延遲應答
如果接收數據的主機立刻返回ACK應答,這時候返回的窗口可能比較小。因為可能會出現應答一發出就有數據被讀取了,那緩沖區就又大一點了,但是應答沒有能夠及時知道
又因為窗口越大,網絡吞吐量就越大,傳輸效率就越高。最終的目標是在保證網絡不擁塞的情況下盡量提高傳輸效率。因此就可以引入延遲應答的機制。
另外還有利用到TCP的應答機制原理,只要將該序號的數據應答回去,那么就說明該序號前的所有數據都已經收到了。所以延遲的時間就可以取在超時重發的時間前。
捎帶應答
在很多情況下,兩端主機都是一發一收的模式在通信,也就是說客戶端給服務端發送數據,服務端也會回一個數據給客戶端。那這個時候搭配著延遲應答,服務端可以在這段時間內將之前處理完的數據。等到服務端發送應答了,一并這數據帶走發送,這樣就可以省下一步,這就是捎帶應答
面向字節流
TCP是以字節流的方式去讀寫的。
在創建TCP的套接字時,操作系統內核會同時創建一個發送緩沖區和一個接收緩沖區
- 調用write時, 數據會先寫入發送緩沖區中;
- 如果發送的字節數太長, 會被拆分成多個TCP的數據包發出;
- 如果發送的字節數太短, 就會先在緩沖區里等待, 等到緩沖區長度差不多了, 或者其他合適的時機發送出去;接收數據的時候, 數據也是從網卡驅動程序到達內核的接收緩沖區;
- 然后應用程序可以調用read從接收緩沖區拿數據;
另外TCP的一個連接, 既有發送緩沖區, 也有接收緩沖區, 那么對于這一個連接, 既可以讀數據, 也可以寫數據. 這個概念叫做 全雙工
由于緩沖區的存在,TCP的讀和寫就不需要一一匹配了,只需要讀寫到指定的字節數就可以
粘包問題
因為字節流的原因,就可能會出現讀取一個數據沒讀完或者讀多了讀了別的數據
因此為了解決這種粘包問題可以采用幾種方案
- 定長讀寫,指定字節數
- 利用分隔符分隔數據
- 約定報頭的位置,在報頭里加上有效載荷的字節數
TCP的異常
- 進程終止:進程終止會釋放文件描述符,仍然可以發送FIN和正常關閉沒有什么區別。
- 機器重啟:和進程終止的情況相同。
- 機器掉電/網線斷開:接收端認為連接還在,一旦接收端有寫入操作,接收端發現連接已經不在了,就會進行reset(重置連接)。即使沒有寫入操作,TCP自己也內置了一個保活定時器,會定期詢問對方是否還在,如果對方不在也會把連接釋放