? 發(fā)布時間:2024-10-14 10:24:59?瀏覽次數(shù):262
作者 | 小林coding
來源 | 小林coding(ID:CodingLin)
相信大家都知道 TCP 是一個可靠傳輸?shù)膮f(xié)議,那它是如何保證可靠的呢?
為了實現(xiàn)可靠性傳輸,需要考慮很多事情,例如數(shù)據的破壞、丟包、重復以及分片順序混亂等問題。如不能解決這些問題,也就無從談起可靠傳輸。
那么,TCP 是通過序列號、確認應答、重發(fā)控制、連接管理以及窗口控制等機制實現(xiàn)可靠性傳輸?shù)摹?/p>
今天,將重點介紹 TCP 的重傳機制、滑動窗口、流量控制、擁塞控制。
提綱
TCP 實現(xiàn)可靠傳輸?shù)姆绞街?,是通過序列號與確認應答。
在 TCP 中,當發(fā)送端的數(shù)據到達接收主機時,接收端主機會返回一個確認應答消息,表示已收到消息。
正常的數(shù)據傳輸
但在錯綜復雜的網絡,并不一定能如上圖那么順利能正常的數(shù)據傳輸,萬一數(shù)據在傳輸過程中丟失了呢?
所以 TCP 針對數(shù)據包丟失的情況,會用重傳機制解決。
接下來說說常見的重傳機制:
超時重傳
快速重傳
SACK
D-SACK
TCP 會在以下兩種情況發(fā)生超時重傳:
數(shù)據包丟失
確認應答丟失
超時重傳的兩種情況
超時時間應該設置為多少呢?
我們先來了解一下什么是 RTT(Round-Trip Time 往返時延),從下圖我們就可以知道:
RTT
RTT 就是數(shù)據從網絡一端傳送到另一端所需的時間,也就是包的往返時間。
超時重傳時間是以 RTO (Retransmission Timeout 超時重傳時間)表示。
假設在重傳的情況下,超時時間 RTO 「較長或較短」時,會發(fā)生什么事情呢?
超時時間較長與較短
上圖中有兩種超時時間不同的情況:
精確的測量超時時間 RTO 的值是非常重要的,這可讓我們的重傳機制更高效。
根據上述的兩種情況,我們可以得知,超時重傳時間 RTO 的值應該略大于報文往返 RTT 的值。
RTO 應略大于 RTT
至此,可能大家覺得超時重傳時間 RTO 的值計算,也不是很復雜嘛。
好像就是在發(fā)送端發(fā)包時記下 t0 ,然后接收端再把這個 ack 回來時再記一個 t1,于是 RTT = t1 – t0。沒那么簡單,這只是一個采樣,不能代表普遍情況。實際上「報文往返 RTT 的值」是經常變化的,因為我們的網絡也是時常變化的。也就因為「報文往返 RTT 的值」 是經常波動變化的,所以「超時重傳時間 RTO 的值」應該是一個動態(tài)變化的值。我們來看看 Linux 是如何計算RTO的呢?
估計往返時間,通常需要采樣以下兩個:
需要 TCP 通過采樣 RTT 的時間,然后進行加權平均,算出一個平滑 RTT 的值,而且這個值還是要不斷變化的,因為網絡狀況不斷地變化。
除了采樣 RTT,還要采樣 RTT 的波動范圍,這樣就避免如果 RTT 有一個大的波動的話,很難被發(fā)現(xiàn)的情況。
RFC6289 建議使用以下的公式計算 RTO:
RFC6289 建議的 RTO 計算
其中 SRTT 是計算平滑的RTT ,DevRTR 是計算平滑的RTT 與 最新 RTT 的差距。
在 Linux 下,α = 0.125,β = 0.25, μ = 1,? = 4。別問怎么來的,問就是大量實驗中調出來的。
如果超時重發(fā)的數(shù)據,再次超時的時候,又需要重傳的時候,TCP 的策略是超時間隔加倍。
也就是每當遇到一次超時重傳的時候,都會將下一次超時時間間隔設為先前值的兩倍。兩次超時,就說明網絡環(huán)境差,不宜頻繁反復發(fā)送。
超時觸發(fā)重傳存在的問題是,超時周期可能相對較長。那是不是可以有更快的方式呢?
于是就可以用「快速重傳」機制來解決超時重發(fā)的時間等待。
TCP 還有另外一種快速重傳(Fast Retransmit)機制,它不以時間為驅動,而是以數(shù)據驅動重傳。
快速重傳機制,是如何工作的呢?其實很簡單,一圖勝千言。
快速重傳機制
在上圖,發(fā)送方發(fā)出了 1,2,3,4,5 份數(shù)據:
第一份 Seq1 先送到了,于是就 Ack 回 2;
結果 Seq2 因為某些原因沒收到,Seq3 到達了,于是還是 Ack 回 2;
后面的 Seq4 和 Seq5 都到了,但還是 Ack 回 2,因為 Seq2 還是沒有收到;
發(fā)送端收到了三個 Ack = 2 的確認,知道了 Seq2 還沒有收到,就會在定時器過期之前,重傳丟失的 Seq2。
最后,接收到收到了 Seq2,此時因為 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。
所以,快速重傳的工作方式是當收到三個相同的 ACK 報文時,會在定時器過期之前,重傳丟失的報文段。
快速重傳機制只解決了一個問題,就是超時時間的問題,但是它依然面臨著另外一個問題。就是重傳的時候,是重傳之前的一個,還是重傳所有的問題。
比如對于上面的例子,是重傳 Seq2 呢?還是重傳 Seq2、Seq3、Seq4、Seq5 呢?因為發(fā)送端并不清楚這連續(xù)的三個 Ack 2 是誰傳回來的。
根據 TCP 不同的實現(xiàn),以上兩種情況都是有可能的??梢?,這是一把雙刃劍。
為了解決不知道該重傳哪些 TCP 報文,于是就有 SACK 方法。
還有一種實現(xiàn)重傳機制的方式叫:SACK( Selective Acknowledgment 選擇性確認)。
這種方式需要在 TCP 頭部「選項」字段里加一個 SACK 的東西,它可以將緩存的地圖發(fā)送給發(fā)送方,這樣發(fā)送方就可以知道哪些數(shù)據收到了,哪些數(shù)據沒收到,知道了這些信息,就可以只重傳丟失的數(shù)據。
如下圖,發(fā)送方收到了三次同樣的 ACK 確認報文,于是就會觸發(fā)快速重發(fā)機制,通過 SACK 信息發(fā)現(xiàn)只有 200~299 這段數(shù)據丟失,則重發(fā)時,就只選擇了這個 TCP 段進行重復。
選擇性確認
如果要支持 SACK,必須雙方都要支持。在 Linux 下,可以通過 net.ipv4.tcp_sack 參數(shù)打開這個功能(Linux 2.4 后默認打開)。
Duplicate SACK 又稱 D-SACK,其主要使用了 SACK 來告訴「發(fā)送方」有哪些數(shù)據被重復接收了。
下面舉例兩個栗子,來說明 D-SACK 的作用。
栗子一號:ACK 丟包
ACK 丟包
「接收方」發(fā)給「發(fā)送方」的兩個 ACK 確認應答都丟失了,所以發(fā)送方超時后,重傳第一個數(shù)據包(3000 ~ 3499)
于是「接收方」發(fā)現(xiàn)數(shù)據是重復收到的,于是回了一個 SACK = 3000~3500,告訴「發(fā)送方」 3000~3500 的數(shù)據早已被接收了,因為 ACK 都到了 4000 了,已經意味著 4000 之前的所有數(shù)據都已收到,所以這個 SACK 就代表著 D-SACK。
這樣「發(fā)送方」就知道了,數(shù)據沒有丟,是「接收方」的 ACK 確認報文丟了。
栗子二號:網絡延時
網絡延時
數(shù)據包(1000~1499) 被網絡延遲了,導致「發(fā)送方」沒有收到 Ack 1500 的確認報文。
而后面報文到達的三個相同的 ACK 確認報文,就觸發(fā)了快速重傳機制,但是在重傳后,被延遲的數(shù)據包(1000~1499)又到了「接收方」;
所以「接收方」回了一個 SACK=1000~1500,因為 ACK 已經到了 3000,所以這個 SACK 是 D-SACK,表示收到了重復的包。
這樣發(fā)送方就知道快速重傳觸發(fā)的原因不是發(fā)出去的包丟了,也不是因為回應的 ACK 包丟了,而是因為網絡延遲了。
可見,D-SACK 有這么幾個好處:
可以讓「發(fā)送方」知道,是發(fā)出去的包丟了,還是接收方回應的 ACK 包丟了;
可以知道是不是「發(fā)送方」的數(shù)據包被網絡延遲了;
可以知道網絡中是不是把「發(fā)送方」的數(shù)據包給復制了;
在 Linux 下可以通過 net.ipv4.tcp_dsack 參數(shù)開啟/關閉這個功能(Linux 2.4 后默認打開)。
引入窗口概念的原因
我們都知道 TCP 是每發(fā)送一個數(shù)據,都要進行一次確認應答。當上一個數(shù)據包收到了應答了, 再發(fā)送下一個。
這個模式就有點像我和你面對面聊天,你一句我一句。但這種方式的缺點是效率比較低的。
如果你說完一句話,我在處理其他事情,沒有及時回復你,那你不是要干等著我做完其他事情后,我回復你,你才能說下一句話,很顯然這不現(xiàn)實。
按數(shù)據包進行確認應答
所以,這樣的傳輸方式有一個缺點:數(shù)據包的往返時間越長,通信的效率就越低。
為解決這個問題,TCP 引入了窗口這個概念。即使在往返時間較長的情況下,它也不會降低網絡通信的效率。
那么有了窗口,就可以指定窗口大小,窗口大小就是指無需等待確認應答,而可以繼續(xù)發(fā)送數(shù)據的最大值。
窗口的實現(xiàn)實際上是操作系統(tǒng)開辟的一個緩存空間,發(fā)送方主機在等到確認應答返回之前,必須在緩沖區(qū)中保留已發(fā)送的數(shù)據。如果按期收到確認應答,此時數(shù)據就可以從緩存區(qū)清除。
假設窗口大小為 3 個 TCP 段,那么發(fā)送方就可以「連續(xù)發(fā)送」 3 個 TCP 段,并且中途若有 ACK 丟失,可以通過「下一個確認應答進行確認」。如下圖:
用滑動窗口方式并行處理
圖中的 ACK 600 確認應答報文丟失,也沒關系,因為可以通話下一個確認應答進行確認,只要發(fā)送方收到了 ACK 700 確認應答,就意味著 700 之前的所有數(shù)據「接收方」都收到了。這個模式就叫累計確認或者累計應答。
窗口大小由哪一方決定?
TCP 頭里有一個字段叫 Window,也就是窗口大小。
這個字段是接收端告訴發(fā)送端自己還有多少緩沖區(qū)可以接收數(shù)據。于是發(fā)送端就可以根據這個接收端的處理能力來發(fā)送數(shù)據,而不會導致接收端處理不過來。
所以,通常窗口的大小是由接收方的決定的。
發(fā)送方發(fā)送的數(shù)據大小不能超過接收方的窗口大小,否則接收方就無法正常接收到數(shù)據。
發(fā)送方的滑動窗口
我們先來看看發(fā)送方的窗口,下圖就是發(fā)送方緩存的數(shù)據,根據處理的情況分成四個部分,其中深藍色方框是發(fā)送窗口,紫色方框是可用窗口:
#1 是已發(fā)送并收到 ACK確認的數(shù)據:1~31 字節(jié)
#2 是已發(fā)送但未收到 ACK確認的數(shù)據:32~45 字節(jié)
#3 是未發(fā)送但總大小在接收方處理范圍內(接收方還有空間):46~51字節(jié)
#4 是未發(fā)送但總大小超過接收方處理范圍(接收方沒有空間):52字節(jié)以后
在下圖,當發(fā)送方把數(shù)據「全部」都一下發(fā)送出去后,可用窗口的大小就為 0 了,表明可用窗口耗盡,在沒收到 ACK 確認之前是無法繼續(xù)發(fā)送數(shù)據了。
可用窗口耗盡
在下圖,當收到之前發(fā)送的數(shù)據 32~36 字節(jié)的 ACK 確認應答后,如果發(fā)送窗口的大小沒有變化,則滑動窗口往右邊移動 5 個字節(jié),因為有 5 個字節(jié)的數(shù)據被應答確認,接下來 52~56 字節(jié)又變成了可用窗口,那么后續(xù)也就可以發(fā)送 52~56 這 5 個字節(jié)的數(shù)據了。
32 ~ 36 字節(jié)已確認
程序是如何表示發(fā)送方的四個部分的呢?
TCP 滑動窗口方案使用三個指針來跟蹤在四個傳輸類別中的每一個類別中的字節(jié)。其中兩個指針是絕對指針(指特定的序列號),一個是相對指針(需要做偏移)。
SND.WND、SND.UN、SND.NXT
SND.WND:表示發(fā)送窗口的大?。ù笮∈怯山邮辗街付ǖ模?/p>
SND.UNA:是一個絕對指針,它指向的是已發(fā)送但未收到確認的第一個字節(jié)的序列號,也就是 #2 的第一個字節(jié)。
SND.NXT:也是一個絕對指針,它指向未發(fā)送但可發(fā)送范圍的第一個字節(jié)的序列號,也就是 #3 的第一個字節(jié)。
指向 #4 的第一個字節(jié)是個相對指針,它需要 SND.UNA 指針加上 SND.WND 大小的偏移量,就可以指向 #4 的第一個字節(jié)了。
那么可用窗口大小的計算就可以是:
可用窗口大 = SND.WND -(SND.NXT - SND.UNA)
接收方的滑動窗口
接下來我們看看接收方的窗口,接收窗口相對簡單一些,根據處理的情況劃分成三個部分:
#1 + #2 是已成功接收并確認的數(shù)據(等待應用進程讀取);
#3 是未收到數(shù)據但可以接收的數(shù)據;
#4 未收到數(shù)據并不可以接收的數(shù)據;
接收窗口
其中三個接收部分,使用兩個指針進行劃分:
RCV.WND:表示接收窗口的大小,它會通告給發(fā)送方。
RCV.NXT:是一個指針,它指向期望從發(fā)送方發(fā)送來的下一個數(shù)據字節(jié)的序列號,也就是 #3 的第一個字節(jié)。
指向 #4 的第一個字節(jié)是個相對指針,它需要 RCV.NXT 指針加上 RCV.WND 大小的偏移量,就可以指向 #4 的第一個字節(jié)了。
接收窗口和發(fā)送窗口的大小是相等的嗎?
并不是完全相等,接收窗口的大小是約等于發(fā)送窗口的大小的。
因為滑動窗口并不是一成不變的。比如,當接收方的應用進程讀取數(shù)據的速度非??斓脑?,這樣的話接收窗口可以很快的就空缺出來。那么新的接收窗口大小,是通過 TCP 報文中的 Windows 字段來告訴發(fā)送方。那么這個傳輸過程是存在時延的,所以接收窗口和發(fā)送窗口是約等于的關系。
發(fā)送方不能無腦的發(fā)數(shù)據給接收方,要考慮接收方處理能力。
如果一直無腦的發(fā)數(shù)據給對方,但對方處理不過來,那么就會導致觸發(fā)重發(fā)機制,從而導致網絡流量的無端的浪費。
為了解決這種現(xiàn)象發(fā)生,TCP 提供一種機制可以讓「發(fā)送方」根據「接收方」的實際接收能力控制發(fā)送的數(shù)據量,這就是所謂的流量控制。
下面舉個栗子,為了簡單起見,假設以下場景:
客戶端是接收方,服務端是發(fā)送方
假設接收窗口和發(fā)送窗口相同,都為 200
假設兩個設備在整個傳輸過程中都保持相同的窗口大小,不受外界影響
流量控制
根據上圖的流量控制,說明下每個過程:
客戶端向服務端發(fā)送請求數(shù)據報文。這里要說明下,本次例子是把服務端作為發(fā)送方,所以沒有畫出服務端的接收窗口。
服務端收到請求報文后,發(fā)送確認報文和 80 字節(jié)的數(shù)據,于是可用窗口 Usable 減少為 120 字節(jié),同時 SND.NXT 指針也向右偏移 80 字節(jié)后,指向 321,這意味著下次發(fā)送數(shù)據的時候,序列號是 321。
客戶端收到 80 字節(jié)數(shù)據后,于是接收窗口往右移動 80 字節(jié),RCV.NXT 也就指向 321,這意味著客戶端期望的下一個報文的序列號是 321,接著發(fā)送確認報文給服務端。
服務端再次發(fā)送了 120 字節(jié)數(shù)據,于是可用窗口耗盡為 0,服務端無法在繼續(xù)發(fā)送數(shù)據。
客戶端收到 120 字節(jié)的數(shù)據后,于是接收窗口往右移動 120 字節(jié),RCV.NXT 也就指向 441,接著發(fā)送確認報文給服務端。
服務端收到對 80 字節(jié)數(shù)據的確認報文后,SND.UNA 指針往右偏移后指向 321,于是可用窗口 Usable 增大到 80。
服務端收到對 120 字節(jié)數(shù)據的確認報文后,SND.UNA 指針往右偏移后指向 441,于是可用窗口 Usable 增大到 200。
服務端可以繼續(xù)發(fā)送了,于是發(fā)送了 160 字節(jié)的數(shù)據后,SND.NXT 指向 601,于是可用窗口 Usable 減少到 40。
客戶端收到 160 字節(jié)后,接收窗口往右移動了 160 字節(jié),RCV.NXT 也就是指向了 601,接著發(fā)送確認報文給服務端。
服務端收到對 160 字節(jié)數(shù)據的確認報文后,發(fā)送窗口往右移動了 160 字節(jié),于是 SND.UNA 指針偏移了 160 后指向 601,可用窗口 Usable 也就增大至了 200。
前面的流量控制例子,我們假定了發(fā)送窗口和接收窗口是不變的,但是實際上,發(fā)送窗口和接收窗口中所存放的字節(jié)數(shù),都是放在操作系統(tǒng)內存緩沖區(qū)中的,而操作系統(tǒng)的緩沖區(qū),會被操作系統(tǒng)調整。
當應用進程沒辦法及時讀取緩沖區(qū)的內容時,也會對我們的緩沖區(qū)造成影響。
那操心系統(tǒng)的緩沖區(qū),是如何影響發(fā)送窗口和接收窗口的呢?
我們先來看看第一個例子。
當應用程序沒有及時讀取緩存時,發(fā)送窗口和接收窗口的變化。
考慮以下場景:
客戶端作為發(fā)送方,服務端作為接收方,發(fā)送窗口和接收窗口初始大小為 360;
服務端非常的繁忙,當收到客戶端的數(shù)據時,應用層不能及時讀取數(shù)據。
根據上圖的流量控制,說明下每個過程:
客戶端發(fā)送 140 字節(jié)數(shù)據后,可用窗口變?yōu)?220 (360 - 140)。
服務端收到 140 字節(jié)數(shù)據,但是服務端非常繁忙,應用進程只讀取了 40 個字節(jié),還有 100 字節(jié)占用著緩沖區(qū),于是接收窗口收縮到了 260 (360 - 100),最后發(fā)送確認信息時,將窗口大小通過給客戶端。
客戶端收到確認和窗口通告報文后,發(fā)送窗口減少為 260。
客戶端發(fā)送 180 字節(jié)數(shù)據,此時可用窗口減少到 80。
服務端收到 180 字節(jié)數(shù)據,但是應用程序沒有讀取任何數(shù)據,這 180 字節(jié)直接就留在了緩沖區(qū),于是接收窗口收縮到了 80 (260 - 180),并在發(fā)送確認信息時,通過窗口大小給客戶端。
客戶端收到確認和窗口通告報文后,發(fā)送窗口減少為 80。
客戶端發(fā)送 80 字節(jié)數(shù)據后,可用窗口耗盡。
服務端收到 80 字節(jié)數(shù)據,但是應用程序依然沒有讀取任何數(shù)據,這 80 字節(jié)留在了緩沖區(qū),于是接收窗口收縮到了 0,并在發(fā)送確認信息時,通過窗口大小給客戶端。
客戶端收到確認和窗口通告報文后,發(fā)送窗口減少為 0。
可見最后窗口都收縮為 0 了,也就是發(fā)生了窗口關閉。當發(fā)送方可用窗口變?yōu)?0 時,發(fā)送方實際上會定時發(fā)送窗口探測報文,以便知道接收方的窗口是否發(fā)生了改變,這個內容后面會說,這里先簡單提一下。
我們先來看看第二個例子。
當服務端系統(tǒng)資源非常緊張的時候,操心系統(tǒng)可能會直接減少了接收緩沖區(qū)大小,這時應用程序又無法及時讀取緩存數(shù)據,那么這時候就有嚴重的事情發(fā)生了,會出現(xiàn)數(shù)據包丟失的現(xiàn)象。
說明下每個過程:
客戶端發(fā)送 140 字節(jié)的數(shù)據,于是可用窗口減少到了 220。
服務端因為現(xiàn)在非常的繁忙,操作系統(tǒng)于是就把接收緩存減少了 100 字節(jié),當收到 對 140 數(shù)據確認報文后,又因為應用程序沒有讀取任何數(shù)據,所以 140 字節(jié)留在了緩沖區(qū)中,于是接收窗口大小從 360 收縮成了 100,最后發(fā)送確認信息時,通告窗口大小給對方。
此時客戶端因為還沒有收到服務端的通告窗口報文,所以不知道此時接收窗口收縮成了 100,客戶端只會看自己的可用窗口還有 220,所以客戶端就發(fā)送了 180 字節(jié)數(shù)據,于是可用窗口減少到 40。
服務端收到了 180 字節(jié)數(shù)據時,發(fā)現(xiàn)數(shù)據大小超過了接收窗口的大小,于是就把數(shù)據包丟失了。
客戶端收到第 2 步時,服務端發(fā)送的確認報文和通告窗口報文,嘗試減少發(fā)送窗口到 100,把窗口的右端向左收縮了 80,此時可用窗口的大小就會出現(xiàn)詭異的負值。
所以,如果發(fā)生了先減少緩存,再收縮窗口,就會出現(xiàn)丟包的現(xiàn)象。
為了防止這種情況發(fā)生,TCP 規(guī)定是不允許同時減少緩存又收縮窗口的,而是采用先收縮窗口,過段時間在減少緩存,這樣就可以避免了丟包情況。
在前面我們都看到了,TCP 通過讓接收方指明希望從發(fā)送方接收的數(shù)據大小(窗口大?。﹣磉M行流量控制。
如果窗口大小為 0 時,就會阻止發(fā)送方給接收方傳遞數(shù)據,直到窗口變?yōu)榉?0 為止,這就是窗口關閉。
窗口關閉潛在的危險
接收方向發(fā)送方通告窗口大小時,是通過 ACK 報文來通告的。
那么,當發(fā)生窗口關閉時,接收方處理完數(shù)據后,會向發(fā)送方通告一個窗口非 0 的 ACK 報文,如果這個通告窗口的 ACK 報文在網絡中丟失了,那麻煩就大了。
窗口關閉潛在的危險
這會導致發(fā)送方一直等待接收方的非 0 窗口通知,接收方也一直等待發(fā)送方的數(shù)據,如不不采取措施,這種相互等待的過程,會造成了死鎖的現(xiàn)象。
TCP 是如何解決窗口關閉時,潛在的死鎖現(xiàn)象呢?
為了解決這個問題,TCP 為每個連接設有一個持續(xù)定時器,只要 TCP 連接一方收到對方的零窗口通知,就啟動持續(xù)計時器。
如果持續(xù)計時器超時,就會發(fā)送窗口探測 ( Windowprobe ) 報文,而對方在確認這個探測報文時,給出自己現(xiàn)在的接收窗口大小。
窗口探測
如果接收窗口仍然為 0,那么收到這個報文的一方就會重新啟動持續(xù)計時器;
如果接收窗口不是 0,那么死鎖的局面就可以被打破了。
窗口探查探測的次數(shù)一般為 3 此次,每次次大約 30-60 秒(不同的實現(xiàn)可能會不一樣)。如果 3 次過后接收窗口還是 0 的話,有的 TCP 實現(xiàn)就會發(fā) RST 報文來中斷連接。
如果接收方太忙了,來不及取走接收窗口里的數(shù)據,那么就會導致發(fā)送方的發(fā)送窗口越來越小。
到最后,如果接收方騰出幾個字節(jié)并告訴發(fā)送方現(xiàn)在有幾個字節(jié)的窗口,而發(fā)送方會義無反顧地發(fā)送這幾個字節(jié),這就是糊涂窗口綜合癥。
要知道,我們的 TCP + IP 頭有 40 個字節(jié),為了傳輸那幾個字節(jié)的數(shù)據,要達上這么大的開銷,這太不經濟了。
就好像一個可以承載 50 人的大巴車,每次來了一兩個人,就直接發(fā)車。除非家里有礦的大巴司機,才敢這樣玩,不然遲早破產。要解決這個問題也不難,大巴司機等乘客數(shù)量超過了 25 個,才認定可以發(fā)車。
現(xiàn)舉個糊涂窗口綜合癥的栗子,考慮以下場景:
接收方的窗口大小是 360 字節(jié),但接收方由于某些原因陷入困境,假設接收方的應用層讀取的能力如下:
接收方每接收 3 個字節(jié),應用程序就只能從緩沖區(qū)中讀取 1 個字節(jié)的數(shù)據;
糊涂窗口綜合癥
每個過程的窗口大小的變化,在圖中都描述的很清楚了,可以發(fā)現(xiàn)窗口不斷減少了,并且發(fā)送的數(shù)據都是比較小的了。
所以,糊涂窗口綜合癥的現(xiàn)象是可以發(fā)生在發(fā)送方和接收方:
接收方可以通告一個小的窗口
而發(fā)送方可以發(fā)送小數(shù)據
于是,要解決糊涂窗口綜合癥,就解決上面兩個問題就可以了
讓接收方不通告小窗口給發(fā)送方
讓發(fā)送方避免發(fā)送小數(shù)據
怎么讓接收方不通告小窗口呢?
接收方通常的策略如下:
當「窗口大小」小于 min( MSS,緩存空間/2 ) ,也就是小于 MSS 與 1/2 緩存大小中的最小值時,就會向發(fā)送方通告窗口為 0,也就阻止了發(fā)送方再發(fā)數(shù)據過來。
等到接收方處理了一些數(shù)據后,窗口大小 >= MSS,或者接收方緩存空間有一半可以使用,就可以把窗口打開讓發(fā)送方發(fā)送數(shù)據過來。
怎么讓發(fā)送方避免發(fā)送小數(shù)據呢?
發(fā)送方通常的策略:
使用 Nagle 算法,該算法的思路是延時處理,它滿足以下兩個條件中的一條才可以發(fā)送數(shù)據:
要等到窗口大小 >= MSS 或是 數(shù)據大小 >= MSS
收到之前發(fā)送數(shù)據的 ack 回包
只要沒滿足上面條件中的一條,發(fā)送方一直在囤積數(shù)據,直到滿足上面的發(fā)送條件。
另外,Nagle 算法默認是打開的,如果對于一些需要小數(shù)據包交互的場景的程序,比如,telnet 或 ssh 這樣的交互性比較強的程序,則需要關閉 Nagle 算法。
可以在 Socket 設置 TCP_NODELAY 選項來關閉這個算法
setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
為什么要有擁塞控制呀,不是有流量控制了嗎?
前面的流量控制是避免「發(fā)送方」的數(shù)據填滿「接收方」的緩存,但是并不知道網絡的中發(fā)生了什么。
一般來說,計算機網絡都處在一個共享的環(huán)境。因此也有可能會因為其他主機之間的通信使得網絡擁堵。
在網絡出現(xiàn)擁堵時,如果繼續(xù)發(fā)送大量數(shù)據包,可能會導致數(shù)據包時延、丟失等,這時 TCP 就會重傳數(shù)據,但是一重傳就會導致網絡的負擔更重,于是會導致更大的延遲以及更多的丟包,這個情況就會進入惡性循環(huán)被不斷地放大….
所以,TCP 不能忽略網絡上發(fā)生的事,它被設計成一個無私的協(xié)議,當網絡發(fā)送擁塞時,TCP 會自我犧牲,降低發(fā)送的數(shù)據量。
于是,就有了擁塞控制,控制的目的就是避免「發(fā)送方」的數(shù)據填滿整個網絡。
為了在「發(fā)送方」調節(jié)所要發(fā)送數(shù)據的量,定義了一個叫做「擁塞窗口」的概念。
什么是擁塞窗口?和發(fā)送窗口有什么關系呢?
擁塞窗口 cwnd是發(fā)送方維護的一個 的狀態(tài)變量,它會根據網絡的擁塞程度動態(tài)變化的。
我們在前面提到過發(fā)送窗口 swnd 和接收窗口 rwnd 是約等于的關系,那么由于入了擁塞窗口的概念后,此時發(fā)送窗口的值是swnd = min(cwnd, rwnd),也就是擁塞窗口和接收窗口中的最小值。
擁塞窗口 cwnd 變化的規(guī)則:
只要網絡中沒有出現(xiàn)擁塞,cwnd 就會增大;
但網絡中出現(xiàn)了擁塞,cwnd 就減少;
那么怎么知道當前網絡是否出現(xiàn)了擁塞呢?
其實只要「發(fā)送方」沒有在規(guī)定時間內接收到 ACK 應答報文,也就是發(fā)生了超時重傳,就會認為網絡出現(xiàn)了用擁塞。
擁塞控制有哪些控制算法?
擁塞控制主要是四個算法:
慢啟動
擁塞避免
擁塞發(fā)生
快速恢復
TCP 在剛建立連接完成后,首先是有個慢啟動的過程,這個慢啟動的意思就是一點一點的提高發(fā)送數(shù)據包的數(shù)量,如果一上來就發(fā)大量的數(shù)據,這不是給網絡添堵嗎?
慢啟動的算法記住一個規(guī)則就行:當發(fā)送方每收到一個 ACK,就擁塞窗口 cwnd 的大小就會加 1。
這里假定擁塞窗口 cwnd 和發(fā)送窗口 swnd 相等,下面舉個栗子:
連接建立完成后,一開始初始化 cwnd = 1,表示可以傳一個 MSS 大小的數(shù)據。
當收到一個 ACK 確認應答后,cwnd 增加 1,于是一次能夠發(fā)送 2 個
當收到 2 個的 ACK 確認應答后, cwnd 增加 2,于是就可以比之前多發(fā)2 個,所以這一次能夠發(fā)送 4 個
當這 4 個的 ACK 確認到來的時候,每個確認 cwnd 增加 1, 4 個確認 cwnd 增加 4,于是就可以比之前多發(fā) 4 個,所以這一次能夠發(fā)送 8 個。
慢啟動算法
可以看出慢啟動算法,發(fā)包的個數(shù)是指數(shù)性的增長。
那慢啟動漲到什么時候是個頭呢?
有一個叫慢啟動門限 ssthresh (slow start threshold)狀態(tài)變量。
當 cwnd < ssthresh 時,使用慢啟動算法。
當 cwnd >= ssthresh 時,就會使用「擁塞避免算法」。
前面說道,當擁塞窗口 cwnd 「超過」慢啟動門限 ssthresh 就會進入擁塞避免算法。
一般來說 ssthresh 的大小是 65535 字節(jié)。
那么進入擁塞避免算法后,它的規(guī)則是:每當收到一個 ACK 時,cwnd 增加 1/cwnd。
接上前面的慢啟動的栗子,現(xiàn)假定 ssthresh 為 8:
當 8 個 ACK 應答確認到來時,每個確認增加 1/8,8 個 ACK 確認 cwnd 一共增加 1,于是這一次能夠發(fā)送 9 個 MSS 大小的數(shù)據,變成了線性增長。
擁塞避免
所以,我們可以發(fā)現(xiàn),擁塞避免算法就是將原本慢啟動算法的指數(shù)增長變成了線性增長,還是增長階段,但是增長速度緩慢了一些。
就這么一直增長著后,網絡就會慢慢進入了擁塞的狀況了,于是就會出現(xiàn)丟包現(xiàn)象,這時就需要對丟失的數(shù)據包進行重傳。
當觸發(fā)了重傳機制,也就進入了「擁塞發(fā)生算法」。
當網絡出現(xiàn)擁塞,也就是會發(fā)生數(shù)據包重傳,重傳機制主要有兩種:
超時重傳
快速重傳
這兩種使用的擁塞發(fā)送算法是不同的,接下來分別來說說。
發(fā)生超時重傳的擁塞發(fā)生算法
當發(fā)生了「超時重傳」,則就會使用擁塞發(fā)生算法。
這個時候,sshresh 和 cwnd 的值會發(fā)生變化:
ssthresh 設為 cwnd/2,
cwnd 重置為 1
擁塞發(fā)送 —— 超時重傳
接著,就重新開始慢啟動,慢啟動是會突然減少數(shù)據流的。這真是一旦「超時重傳」,馬上回到解放前。但是這種方式太激進了,反應也很強烈,會造成網絡卡頓。
就好像本來在秋名山高速漂移著,突然來個緊急剎車,輪胎受得了嗎。。。
發(fā)生快速重傳的擁塞發(fā)生算法
還有更好的方式,前面我們講過「快速重傳算法」。當接收方發(fā)現(xiàn)丟了一個中間包的時候,發(fā)送三次前一個包的 ACK,于是發(fā)送端就會快速地重傳,不必等待超時再重傳。
TCP 認為這種情況不嚴重,因為大部分沒丟,只丟了一小部分,則 ssthresh 和 cwnd 變化如下:
cwnd = cwnd/2 ,也就是設置為原來的一半;
ssthresh = cwnd;
進入快速恢復算法
快速重傳和快速恢復算法一般同時使用,快速恢復算法是認為,你還能收到 3 個重復 ACK 說明網絡也不那么糟糕,所以沒有必要像 RTO 超時那么強烈。
正如前面所說,進入快速恢復之前,cwnd 和 ssthresh 已被更新了:
cwnd = cwnd/2 ,也就是設置為原來的一半;
ssthresh = cwnd;
然后,進入快速恢復算法如下:
擁塞窗口 cwnd = ssthresh + 3 ( 3 的意思是確認有 3 個數(shù)據包被收到了)
重傳丟失的數(shù)據包
如果再收到重復的 ACK,那么 cwnd 增加 1
如果收到新數(shù)據的 ACK 后,設置 cwnd 為 ssthresh,接著就進入了擁塞避免算法
快速重傳和快速恢復
也就是沒有像「超時重傳」一夜回到解放前,而是還在比較高的值,后續(xù)呈線性增長。
資料:
[1] 趣談網絡協(xié)議專欄.劉超.極客時間
[2] Web協(xié)議詳解與抓包實戰(zhàn)專欄.陶輝.極客時間
[3] TCP/IP詳解 卷1:協(xié)議.范建華 譯.機械工業(yè)出版社
[4] 圖解TCP/IP.竹下隆史.人民郵電出版社
[5] The TCP/IP Guide.Charles M. Kozierok.
[6] TCP那些事(上).陳皓.酷殼博客.https://coolshell.cn/articles/11564.html
[7] TCP那些事(下).陳皓.酷殼博客.https://coolshell.cn/articles/11609.html
今日福利
遇見大咖
由 CSDN 全新專為技術人打造的高端對話欄目《大咖來了》來啦!
CSDN 創(chuàng)始人&董事長、極客幫創(chuàng)投創(chuàng)始合伙人蔣濤攜手京東集團技術副總裁、IEEE Fellow、京東人工智能研究院常務副院長、深度學習及語音和語言實驗室負責人何曉冬,來也科技 CTO 胡一川,共話中國 AI 應用元年來了,開發(fā)者及企業(yè)的路徑及發(fā)展方向!
1.膠管老化、破裂或者脫落,這時候就要更新或者重新更換膠管;
2.爐頭主火未點燃,這時候就要等燃氣散盡后再點火;
3.閥體密封不嚴,這時候就要更換閥體;
4.閥體密封圈老化,這時候就要更換密封圈;
5.使用灶具的空間通風不好,這時候就要使用空間通風。
1、首先我們當然需要排除外在的因素導致的臭味,看看家里面使用的燃氣灶以及有多久沒有清洗清潔了,主要的問題就在于燃氣灶的底部一起灶頭的下面,是不是殘留著大量的食物,導致變質而發(fā)出臭味,將整個燃氣灶都清理一遍,包括灶頭火蓋上的網眼。
2、天然氣本身是無色無味的,但是由于它的特性以及天然氣的廣泛使用率,出現(xiàn)事故的可能還是存在,主要表現(xiàn)在泄漏后的危險,而無色無味的天然氣如果泄漏,我們肯定在第一時間無法察覺,那么怎么辦呢?工程師們就想到了一種辦法,往天然氣中添加一種能夠讓人警覺的氣體,而這種氣體既不會影響燃燒,也不會產生危險,關鍵還容易讓人察覺。
(此處已添加小程序,請到今日頭條客戶端查看)
于是天然氣中人工添加的氣體就是四氫噻吩,它的優(yōu)勢就是臭味很足、不容易消散、便于長距離輸送、也不會有沉積物、關鍵不容易被水沖洗掉,由此這種作為警告使用的氣體得到全世界天然氣供應商的使用。
1、 在燃氣灶使用過程中必須打開窗戶或換氣扇以保持室內空氣的流通。
2、 在使用過程中,請不要用手接觸灶具臺面,以防燙傷。
3、 為了使定時器定時準確,旋鈕先轉動幅度大一點,然后再回轉到想要的定時時間。當不使用定時器時,請把定時器按鈕開關轉到“ON”位置。
4、 當發(fā)現(xiàn)燃燒器火焰參差不齊時,可用刷子或鋼針清除噴火器上的污垢。
5、 清洗灶具臺面時,請用柔軟的棉布或毛巾蘸取足量的中性清潔液。
6、 噴火器、火蓋、鍋架清洗完后,必須等到干燥后再正確安裝。
7、 長時間不使用燃氣灶,務必取出干電池;同時還要定期換干電池。
8、 橡膠管使用時間不得超過18個月。
*以上部分圖文源自網絡,侵刪聯(lián)系。
從國家層面的戰(zhàn)略決策,到地方政府刺激消費的家電補貼,再到主流廠商的促銷讓利……一系列瞄準中國家庭老舊家電的換新迭代,正在消費市場掀起新一輪的換代潮,廚房電器也不例外。繼洗碗機、集成灶、成套廚電等成為換代關鍵詞后,占據廚電C位的戰(zhàn)略品類——灶具也進入換代升級期。
上溯到柴火灶、土灶、鐵爐的舊時代,灶具就已經是家家戶戶廚房的必備。直到今天,煙火氣仍是中國廚房幸福的代名詞,灶具也是廚房的最不可或缺。要想真正升級廚房體驗,占據廚房標配C位的灶具,必然需要來一次徹底的換代更新。方太全新的HECB.D燃氣灶就承擔起了這一使命!
之所以是方太率先引爆這一潮流,背后的原因也很簡單:深耕中國廚房近30年,最快洞察到用戶需求,并進行一系列的產品和技術創(chuàng)新。更值得關注的是,秉承“創(chuàng)新的源泉是仁愛,創(chuàng)新的目標是幸福”理念,方太灶具以全新的“好火力、易清潔、好操控、更安全”四維標準,在重新定義好灶具的同時,更打造了“幸福廚房”的生活體驗。
萬事已備,灶具換新潮洶涌而來
“促進家電家具家裝消費,鼓勵有條件的地區(qū)對淘汰舊家電家具并購買綠色智能家電、環(huán)保家具給予補貼?!?020年度,來自國家的這一戰(zhàn)略部署,再次為家電消費送上一份政策“禮包”。
如果梳理2019年以來相關的政策會發(fā)現(xiàn),作為“擴大內需,促進消費”重要力量的老舊家電的換新,已被國家以及北京、廣東、山東、廣西、貴州等地方政府鎖定并積極推動。
僅政策層面一項,就多次為家電更新迭代按下加速鍵。另一方面,則是伴隨生活水平的快速提升,消費升級的大勢讓傳統(tǒng)老舊產品無法滿足用戶新需求。正如商務部研究院流通與消費研究所副所長關利欣所說,政策利好、技術進步、居民收入提升等因素驅動下,用戶對家電產品的升級需求漸趨明顯。
對自始至終承擔著中國廚房最重要烹飪角色、卻常常被忽視的灶具而言,同樣也迎來政策推動和需求升級等多重利好。從需求端來看,“家用燃氣灶的火力不夠大;智能化操作怎么才能更方便快捷?能不能保證灶具的使用更安全?都2020年了,還浪費這么多時間在廚房清潔上……”一系列用戶對傳統(tǒng)灶具的吐槽也在呼吁產業(yè)來一場迭代。
實際上,近年來,灶具行業(yè)在技術創(chuàng)新、功能升級、產品迭代等層面一直探索求變,尤其是行業(yè)領軍者的方太更是如此。以全新方太HECB.D燃氣灶這一明星產品最具代表性。立足中國用戶使用體驗,該產品給出了覆蓋安全、清潔、火力、便捷等方面的全新定義,一經上市已迅速點燃用戶的換新熱情,成為這一波灶具迭代的主力軍。
大火力≠好灶具,系統(tǒng)方案定義好廚火
說到好灶具的標準,大火力顯然不是全部,只是使用體驗的基礎。方太新燃氣灶以增壓直噴系統(tǒng)配合首創(chuàng)的隔熱聚能罩,熱負荷達到5kw,有效火力高達3.5kW,熱效率提高75%,而且燃燒時熱量不會四散。正因如此,方太燃氣灶贏得不少用戶“火猛但不燎人,油溫上升快、炒菜出鍋快,而且小火煲湯更穩(wěn)定”的使用反饋。
“我是想給父母換灶具,老人年紀大了總忘事,最怕的就是用起來忘了關火?!北本┑膭⑴繉υ罹叩膿Q代需求則更為明確——安全。有了方太HECB.D燃氣灶:小火慢燉可以使用左右分控大屏定時器,不用操心關火問題;針對溢鍋的狀況有熄火保護裝置;加上五重防爆面板、安全傘+雙針點火、防回火罩等12項安全保護和童鎖設計,是當前燃氣灶安全使用的最高標準。
劉女士在了解方太灶具后,立馬下單一臺送到父母家中。而B站一位小有名氣的美食博主,已經開始主動給粉絲安利這款產品了:“即開即燃,而且有七檔可視化精控火,爆炒精燉都能精準掌握火候”;“操控方便,憑手感就能換擋。感覺我不像在炒菜,像在賽車”;“鴛鴦鍋架設計,圓底鍋、平底鍋,我這么多鍋今天終于找到好歸宿了”、“煙灶連動,這光影套系是不是很炫酷”……
從點火到控火,再到各種細節(jié)設計,方太HECB.D燃氣灶足以讓美食博主為之傾倒。而其黑晶板的面板構造;聚能罩、盛液盤、鍋支架功能三合一;聚能罩的凹槽設計;爐頭檐式防堵火蓋等等,不但防污還減少湯汁外流,大大減少清潔灶具的工作強度和難度。
對中國人來說,一桌菜代表家的味道,而背后的烹飪體驗更是美好生活的一部分。顯然,扎根中國廚房多年,方太早已對廚火有了更深刻的情感認知。因此,方太眼中的好灶具最先顛覆了“大火力就是好灶”的傳統(tǒng)概念,而是從“火力、清潔、操控、安全”等更全面的維度思考灶具如何貼近生活,并且改變生活。
在方太全新定義下,廚電產業(yè)和中國廚房更新?lián)Q代的聚光燈,也從解放雙手的洗碗機、帶來全新烹飪方式的微蒸烤一體機、更符合整體家裝風格的嵌入式和集成灶等新品類和新趨勢身上,聚焦到傳統(tǒng)灶具身上。方太用一臺好灶,正引爆新一輪廚電更新?lián)Q代潮,更將持續(xù)溫暖“萬家廚火”。
2021年,尼泊爾一家餐館的餐具未經過消毒就供應給客人,導致多人食物中毒。在日常生活中,餐具是人們必不可少的器具之一,但是餐具不消毒會對人們的健康和生命造成嚴重危害。未經過消毒的餐具可能會受到細菌和病毒的污染,將這些餐具用于食品的制作和食用,不僅會影響食品的口感和質量,還會引起食品中毒等健康問題。因此,消毒餐具是確保食品安全的基本措施之一。消毒柜可以利用高溫蒸汽和紫外線等技術,快速殺滅細菌和病毒,有效保障餐具的衛(wèi)生和安全。那么消毒柜哪個牌子好?消費者該如何選購呢?
消毒柜哪個牌子好?方太TM01
結構:消毒柜的外殼結構決定了消毒柜的整體穩(wěn)定性和美觀性。在選擇消毒柜時,人們需要選擇外殼結構穩(wěn)定、材質堅固、外觀美觀的消毒柜,以保證消毒柜的使用壽命和外觀效果。
面板:消毒柜的操作面板通常包括開關、溫度調節(jié)器、定時器等。在選擇消毒柜時,人們需要選擇操作面板簡單易用、功能齊全的消毒柜,這樣可以提高消毒柜的使用效率和便捷性。
消毒柜哪個牌子好?方太TM01
容量:容量是選擇消毒柜時需要關注的一個重要因素。人們需要根據餐具種類和大小選擇消毒柜的容量。不同種類的餐具(如碗、盤、勺、叉、刀等)大小不同,需要根據實際情況選擇不同容量的消毒柜。如果需要消毒大型餐具,那么需要選擇容量較大的消毒柜,否則可能會影響消毒效果。
安全保護:消毒柜的安全保護是非常重要的,包括過溫保護、漏電保護和運轉保護等。在選擇消毒柜時,人們需要選擇具有完善的安全保護措施的消毒柜,以保障消毒柜的安全性和穩(wěn)定性。
消毒柜哪個牌子好?方太TM01
隨著科技的發(fā)展,消毒柜也在不斷進行技術創(chuàng)新,提高消毒效率和安全性。其中,方太TM01采用360°脈沖快消科技,利用了光化學反應、閃照熱效應和脈沖效應等多種技術手段,大大提高了消毒柜的效果和安全性。同時,這款消毒柜還自帶自動感應殺菌系統(tǒng),能夠快速殺滅餐具表面的細菌和病毒。重要的是,這款消毒柜全程無臭氧味,人們可以更加放心地使用。地暖式均勻加熱技術,將腔內溫度迅速提升至75℃,在短時間內,該消毒柜能夠對餐具進行全面的消毒和烘干,讓餐具恢復清新和干燥。
消毒柜哪個牌子好?方太TM01無臭氧味+地暖式均勻加熱技術+自動感應殺菌系統(tǒng),能夠快速殺菌和烘干餐具,同時還能讓用戶盡享清新體驗。作為消毒柜行業(yè)的一款創(chuàng)新產品,相信它會給廣大消費者帶來更加便捷和健康的使用體驗。
維修師傅服務態(tài)度很好,快速的解決了問題,維修速度很快很專業(yè)
不知道是因為什么原因,師傅上門來給我檢查了,告訴我了是什么原因,什么問題,然后我就讓他修了,修理的很好,價格收費什么的也很合理
師傅服務態(tài)度很好,按約定好的時間很準時到了,維修很專業(yè),一會兒功夫就給修好了,現(xiàn)在終于可以正常運作了
師父上門維修特別快,很仔細很認真,工作態(tài)度端正,而且其他問題也能幫忙處理沒有收其他費用很滿意
預約了師傅馬上來上門來了,費用還是可以接受的,師傅態(tài)度做事不錯
有專業(yè)的技術的人員,都擁有專業(yè)的培訓,服務質量好,態(tài)度滿意,價格合理
收費合理,師傅上門準時。態(tài)度挺好
找了師傅上門,檢查后說是線路故障了,換了一下,半個小時就修好了,很專業(yè)
下單后師傅很快就聯(lián)系我了,跟師傅電話聊好價格就上門了,換了顯示面板、目前沒有再繼續(xù)亂響。
已修好,師傅服務周到,態(tài)度很好