日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络:TCP维护安全可靠机制提供的定时器

發布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络:TCP维护安全可靠机制提供的定时器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、TCP為維護安全可靠機制提供了七大定時器

?

1、連接建立(connectionestablishment)”定時器

?????? 在發送SYN報文段建立一條新連接時啟動。如果在75秒內沒有收到響應,連接建立將中止。

?

2、重傳(retransmission)定時器

?????? 在TCP發送某個數據段時設定。如果該定時器超時而對端的確認還未到達,TCP將重傳該數據段。重傳定時器的值 (即TCP等待對端確認的時間)是動態計算的,與RTT的估計值密切相關,且還取決于該報文段已被重傳的次數。

?

3、延遲ACK(delayedACK)定時器

?????? 在TCP收到必須被確認但無需馬上發出確認的數據時設定。如果在200ms內,有數據要在該連接上發送,延遲的ACK響應就可隨著數據一起發送回對端,稱為捎帶確認。如果200ms后,該確認未能被捎帶出去,則定時器超時,此時需要發送一個立即確認。

?

4、持續(persist)定時器(零窗口探測定時器(PT0))

?????? 在連接對端通告接收窗口為0,阻止TCP繼續發送數據時設定。由于連接對端發送的窗口通告不可靠(只有數據才會被確認,ACK不會被確認),允許TCP繼續發送數據的后續窗口更新有可能丟失。因此,如果TCP有數據要發送,但對端通告接收窗口為0,則持續定時器啟動,超時后向對端發送 1字節的數據,判定對端接收窗口是否已打開。

?

5、保活(keepalive)定時器

?????? 在TCP控制塊的so_options 字段設置了SOF_KEEPALIVE選項時生效。如果連接的連續空閑時間超過2小時,則保活定時器超時,此時應向對端發送連接探測報文段,強迫對端響應。如果收到了期待的響應, TCP可確定對端主機工作正常,在該連接再次空閑超過 2小時之前,TCP不會再進行保活測試。如果收到的是RST復位響應, TCP可確定對端主機已重啟。如果連續若干次保活測試都未收到響應, TCP就假定對端主機已崩潰,但它無法區分是主機故障還是連接故障。

?

6、FIN_WAIT_2定時器

?????? 當某個連接從FIN_WAIT_1狀態變遷到FIN_WAIT_2狀態并且不能再接收任何新數據時,FIN_WAIT_2定時器啟動,設為10分鐘。定時器超時后,重新設為75秒,第二次超時后連接被關閉。加入這個定時器的目的是為了避免如果對端一直不發送 FIN,某個連接會永遠滯留在FIN _ WAIT_ 2狀態(假設TCP不選用半打開功能)。

?

7、TIME_WAIT定時器(2MSL定時器)

?????? 2MSL指兩倍的MSL,即最大報文段生存時間。當連接轉移到TIME_WAIT狀態,即連接主動關閉時,定時器啟動。狀態轉換圖那一節中已經詳細說明了需要2MSL等待狀態的原因。連接進入TIME_WAIT狀態時,定時器設定為1分鐘,超時后,TCP控制塊被刪除,端口號可重新使用。

?

8、SYN|ACK定時器

?????? TCP服務器在收到SYN請求后發送SYN|ACK響應,TCP在發送SYN|ACK響應后設置SYN-ACK定時器,然后等待對端的ACK到來以完成三次握手。如果沒有收到ACK,TCP應該重傳SYN|ACK,這個功能由SYN-ACK定時器完成。由于SYN|ACK發送后并沒有放入發送隊列中,故重傳時必須重新構建SYN|ACK報文。?

?

9、ER延時定時器

?????? TCP發送的數據如果丟失則快速重傳算法會立即重傳數據而不用等到重傳定時器超時,從而快速地恢復數據。如果發送端接收不到足夠數量(一般來說是3個)的ACK,則快重傳算法無法起作用,這個時候就只能等待RTO超時。ER算法主要是為了解決這個問題。

?????? 在下面的條件下,就會導致收不到足夠的ACK:

?????? (1)擁塞窗口比較小

?????? (2)窗口中一個很大數量的段丟失或者在傳輸的結尾處發生了丟包

???????? 如果滿足了上面的兩個條件,那么就會發生發送端由于接收不到足夠數量的ACK導致ER可以基于兩種模式,一種是基于字節的,一種是基于段(segment-based)的,Linux中的ER是基于段的。ER算法會在小窗口下(flight count 小于4)減小觸發快重傳的重復ACK的閾值,比如減小到1或者2。而在Linux的實現中為了防止假超時會加上一個延遲再重傳數據,這個功能就靠ER定時器實現。快重傳算法無法生效.

?

?????? 在這些條件滿足后,ER定時器會被設置,其超時時間是一個比重傳定時器更小的值。

??????? 安裝丟失探測定時器、重傳定時器、堅持定時器時ER定時器就會被清除。

??????

?????? (1)有丟包事件發生

?????? (2)重復的ACK小于等于亂序的閾值

?????? (3)未開啟FACK,或沒有未收到確認的包,或隊列首包已發送但未超時

?????? (4)已發送的數據 > 亂序的閾值,或被SACK段的數量小于閾值,或允許發送skb

(5)thin_dupack功能未開啟,或當前鏈接并不是"thin"的,或重復ACK的數量大于1,或SACK未開啟,或有要發送的數據

?????? (6)do_early_retrans開啟

?????? (7)沒有重傳完畢但沒有確認的報文

?????? (8)有被SACK的報文

?????? (9)在網絡中的報文數量比被SACK的報文數量多至少1個

?????? (10)在網絡中的報文數量少于4

?????? (11)現在不允許發送數據

?????? (12)sysctl_tcp_early_retrans的值是2或3

?????? (13)ACK中沒有ECE標記

?????? (14)tp->srtt(smoothed round trip time)的值大于0

?????? (15)icsk->icsk_retransmit_timer超時時間在延遲時間之后

??????????? 值得注意的是在快速重傳時不會重傳已經被SACK過或被重傳過的skb,這些skb也許能夠順利收到,在這里不重傳會減小網絡擁塞。

?

?

雖然定義了9個定時器,但是內核中只用了4個實例(timer_list),所以有些定時器是共用一個實例的。

這4個實例分別是:

icsk->icsk_retransmit_timer:超時重傳定時器、持續定時器、ER延遲定時器、PTO定時器。

icsk->icsk_delack_timer:ACK延遲定時器。

sk->sk_timer:保活定時器,SYNACK定時器,FIN_WAIT2定時器。

death_row->tw_timer:TIME_WAIT定時器

?

?

二、TCP要保證正常工作,至少應該有四種計時器:重傳計時器、持久計時器、保活計時器和時間等待計時器。

?

1、??? 重傳計時器:

?

超時重傳是TCP協議保證數據可靠性的另一個重要機制,其原理是在發送某一個數據以后就開啟一個計時器,在一定時間內如果沒有得到發送的數據報的ACK報文,那么就重新發送數據,直到發送成功為止。當TCP發送報文段時,就創建該特定報文段的重傳計時器。

可能發生兩種情況:

?1) 若在計時器截止時間到之前收到了對此特定報文段的確認,則撤銷此計時器。

?2)收到了對此特定報文段的確認之前計時器截止期到,則重傳此報文段,并將計時器復位。

?

1.重傳超時時間:

?

???重傳機制協議效率的一個關鍵參數是重傳超時時間(RTO,Retransmission TimeOut)。RTO的值被設置過大過小都會對協議造成不利影響。如果RTO設置過大將會使發送端經過較長時間的等待才能發現報文段丟失,降低了連接數據傳輸的吞吐量;另一方面,若RTO過小,發送端盡管可以很快地檢測出報文段的丟失,但也可能將一些延遲大的報文段誤認為是丟失,造成不必要的重傳,浪費了網絡資源。

如果底層網絡的傳輸特性是可預知的,那么重傳機制的設計相對簡單得多,可根據底層網絡的傳輸時延的特性選擇一個合適的RTO,使協議的性能得到優化。但是TCP的底層網絡環境是一個完全異構的互聯結構。在實現端到端的通信時,不同端點之間傳輸通路的性能可能存在著巨大的差異,而且同一個TCP連接在不同的時間段上,也會由于不同的網絡狀態具有不同的傳輸時延。

因次,TCP協議必須適應兩個方面的時延差異:一個是達到不同目的端的時延的差異,另一個是統一連接上的傳輸時延隨業務量負載的變化而出現的差異。為了處理這種底層網絡傳輸特性的差異性和變化性,TCP的重傳機制相對于其他協議顯然也將更為復雜,其復雜性主要表現在對超時時間間隔的處理上。為此,TCP協議使用自適應算法(AdaptiveRetransmissionAlgorithm)以適應互聯網分組傳輸時延的變化。這種算法的基本要點是TCP監視每個連接的性能(即傳輸時延),由此每一個TCP連接推算出合適的RTO值,當連接時延性能變化時,TCP也能夠相應地自動修改RTO的設定,以適應這種網絡的變化。

??

2.連接往返時間:

?

??個連接而言,若能夠了解端點間的傳輸往返時間(RTT,Round Trip Time),則可根據RTT來設置一合適的RTO。顯然,在任何時刻連接的RTT都是隨機的,無法事先預知。TCP通過測量來獲得連接當前RTT的一個估計值,并以該RTT估計值為基準來設置當前的RTO。自適應重傳算法的關鍵就在于對當前RTT的準確估計,以便適時調整RTO。

為了搜集足夠的數據來精確地估算當前的RTT,TCP對每個報文都記錄下發送出的時間和收到的確認時間。每一個(發送時間,確認時間)對就可以計算出一個RTT測量值的樣本(Sample RTT)。TCP為每一個活動的連接都維護一個當前的RTT估計值。該值是對已經過去的一個時間段內該連接的RTT了兩只的加權平均,并作為TCP對連接當前實際的RTT值的一種估計。RTT估計值將在發送報文段時被用于確定報文段的RTO。為了保證它能夠比較準確地反應當前的網絡狀態,每當TCP通過測量獲得了個新的RTT樣本時,都將對RTT的估計值進行更新。不同的更新算法或參數可能獲得不同的特性。[1]

最早的TCP曾經用了一個非常簡單的公式來估計當前網絡的狀況,如下

R<-aR+(1-a)MRTP=Rb其中a是一個經驗系數為0.1,b通常為2。注意,這是經驗,沒有推導過程,這個數值是可以被修改的。這個公式是說用舊的RTT(R)和新的RTT (M)綜合到一起來考慮新的RTT(R)的大小。但又可以看到,這種估計在網絡變化很大的情況下完全不能做出“靈敏的反應”,于是就有下面的修正公式:

Err=M-AA<-A+gErrD<-D+h(|Err|-D)RTO=A+4D,這個遞推公式甚至把方差這種統計概念也使用了進來,使得偏差更加的小。而且,必須要指出的是,這兩組公式更新,都是在 數據成功傳輸的情況下才進行,在發生數據重新傳輸的情況下,并不使用上面的公式進行網絡估計,理由很簡單,因為程序已經不在正常狀態下了,估計出來的數據也是沒有意義的。

如果在一個報文段中的數據被一次性地成功傳輸和確認,那么發送端可以準確得到該報文段傳輸的RTT樣本。但若出現了重傳,情況就會變得很復雜。例如,一個報文段發送后出現超時,TCP將在另一個報文段中重傳。由于這兩個報文段包含了同樣的數據,發送方接收到確認信息時將無法分辨出確認信息到底是針對哪個報文段的,因為這兩個報文段產生的確認信息可能是完全相同的,確認信息既可能是針對原始報文段的(這種情況可能是由于原報文段或確認在傳輸中被延遲造成的),也可能是對重傳報文段的確認。這種現象稱為確認二義性(Acknowledgement Ambiguiity)。確認的二義性將導致TCP無法準確地估算RTT。

為了避免確認二義性帶來的問題,TCP采用了Karn算法來維護RTT的估計值。Karn算法規定,TCP只能利用沒有確認二義性(既無重發、一次發送成功并得到確認的報文段)的RTT樣本來對RTT的估計值進行調整。

?

?

?

2、??? 堅持計時器

?

??? 過讓接收方指明希望從發送方接收的數據字節數(即窗口大小)來進行流量控制。如果窗口大小為 0,這將有效地阻止發送方傳送數據,直到窗口變為非0為止。TCP不對ACK報文段進行確認, TCP只確認那些包含有數據的ACK報文段。如果一個確認丟失了,則雙方就有可能因為等待對方而使連接終止:接收方等待接收數據(因為它已經向發送方通告了一個非 0的窗口),而發送方在等待允許它繼續發送數據的窗口更新。為防止這種死鎖情況的發生,發送方使用一個堅持定時器 (persist timer)來周期性地向接收方查詢,以便發現窗口是否已增大。這些從發送方發出的報文段稱為窗口探查 (window? probe)。這個報文段只有一個字節的數據。它有一個序號,但它的序號永遠不需要確認;甚至在計算對其他部分的數據的確認時該序號也被忽略。探測報文段提醒接收TCP:確認已丟失,必須重傳。

堅持計時器的值設置為重傳時間的數值。但是,若沒有收到從接收端來的響應,則需發送另一個探測報文段,并將堅持計時器的值加倍和復位。發送端繼續發送探測報文段,將堅持計時器設定的值加倍和復位,直到這個值增大到門限值(通常是60秒)為止。在這以后,發送端每隔60秒就發送一個探測報文段,直到窗口重新打開。

?

3、??? 保活計時器

?

??????? 保活計時器使用在某些實現中,用來防止在兩個TCP之間的連接出現長時期的空閑。假定客戶打開了到服務器的連接,傳送了一些數據,然后就保持靜默了。也許這個客戶出故障了。在這種情況下,這個連接將永遠地處理打開狀態。

要解決這種問題,在大多數的實現中都是使服務器設置保活計時器。每當服務器收到客戶的信息,就將計時器復位。超時通常設置為2小時。若服務器過了2小時還沒有收到客戶的信息,它就發送探測報文段。若發送了10個探測報文段(每一個相隔75秒)還沒有響應,就假定客戶出了故障,因而就終止該連接。

這種連接的斷開當然不會使用四次握手,而是直接硬性地中斷和客戶端的TCP連接。

??? 如果一個給定的連接在兩個小時之內沒有任何動作,則服務器就向客戶發送一個探查報文段。客戶機處于以下4種狀態之一時,發送探查報文。

1、客戶主機依然正常運行,并從服務器可達。客戶機的TCP響應正常,而服務器也知道對方正常工作的。服務器在兩小時以后將保活定時器復位,如果在兩個小時定時器到時間之前有應用程序的通信量通過此連接,則定時器在交換數據后的未來2小時復位。

?

2、客戶機已經崩潰,并且關閉或正在重新啟動,在任何一種情況下,客戶的TCP都沒有響應,服務器將不能夠收到對探查的響應,并在75秒后超時,服務器總共發送10個這樣的探查,每個間隔75秒,如果服務器沒有收到一個響應,它就認為客戶主機已經關閉并終止連接。

socket函數會返回-1,errno設置為ETIMEDOUT,表示連接超時。

?

3、客戶主機崩潰并已經重新啟動,這時服務器將收到一個對其保活探查的響應,但是這個響應是一個復位,使得服務器終止這個連接。客戶端的TCP發送RST,服務器端收到后關閉此連接。

socket函數會返回-1,errno設置為ECONNRESET,表示連接被對端復位了

?

4、客戶機正常運行,但是從服務器不可達,這與狀態2相同,因為TCP不能夠區分狀態4與狀態2之間的區別,它所能發現的就是沒有收到探查的響應。

服務器不用關注客戶主機被關閉和重新啟動的情況,當系統被操作員半閉時,所的應用進程也被終止,這會使客戶的TCP在連接上發了一個FIN,接收到FIN將使服務器的TCP響服務器進程報告文件結束,使服務器可以檢測到這個情況。雙方的反應和第二種是一樣的,因為服務器不能區分對端異常與中間鏈路異常。

socket函數會返回-1,errno設置為EHOSTUNREACH,表示對端不可達

?

內核默認并不使用TCPKeepalive功能,除非用戶設置了SO_KEEPALIVE選項。

有兩種方式可以自行調整保活定時器的參數:一種是修改TCP參數,一種是使用TCP層選項。

?

(1) TCP參數

tcp_keepalive_time

最后一次數據交換到TCP發送第一個保活探測報文的時間,即允許連接空閑的時間,默認為7200s。

tcp_keepalive_intvl

保活探測報文的重傳時間,默認為75s。

tcp_keepalive_probes

保活探測報文的發送次數,默認為9次。

?一次完整的保活探測需要花費時間tcp_keepalive_time + tcp_keepalive_intvl*tcp_keepalive_probes,默認值為7875s。

如果覺得兩個多小時太長了,可以自行調整上述參數。

?

(2) TCP層選項

TCP_KEEPIDLE:含義同tcp_keepalive_time。

TCP_KEEPINTVL:含義同tcp_keepalive_intvl。

TCP_KEEPCNT:含義同tcp_keepalive_probes。

??? TCP參數是面向本機的所有TCP連接,一旦調整了,對所有的連接都有效。

而TCP層選項是面向一條連接的,一旦調整了,只對本條連接有效。

?激活

?在連接建立后,可以通過設置SO_KEEPALIVE選項,來激活保活定時器。

int keepalive = 1;

setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,&keepalive,sizeof(keepalive));

可以使用TCP層選項來動態調整保活定時器的參數。

int keepidle = 600;

int keepintvl = 10;

int keepcnt = 6;

setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepidle,sizeof(keepidle));

setsockopt(fd, SOL_TCP, TCP_KEEPINTVL,&keepintvl,sizeof(keepintvl));

setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepcnt,sizeof(keepcnt));

?

LinuxSO_KEEPALIVE屬性,心跳包

對于面向連接的TCP socket,在實際應用中通常都要檢測對端是否處于連接中,連接端口分兩種情況:

1、連接正常關閉,調用close() shutdown()連接優雅關閉,send與recv立馬返回錯誤,select返回SOCK_ERR;

2、連接的對端異常關閉,比如網絡斷掉,突然斷電.

對于第二種情況,判斷連接是否斷開的方法有一下幾種:

1、自己編寫心跳包程序,簡單的說就是自己的程序加入一條線程,定時向對端發送數據包,查看是否有ACK,根據ACK的返回情況來管理連接。此方法比較通用,一般使用業務層心跳處理,靈活可控,但改變了現有的協議;

2、使用TCP的keepalive機制,UNIX網絡編程不推薦使用SO_KEEPALIVE來做心跳檢測。

keepalive原理:TCP內嵌有心跳包,以服務端為例,當server檢測到超過一定時間(/proc/sys/net/ipv4/tcp_keepalive_time7200 即2小時)沒有數據傳輸,那么會向client端發送一個keepalivepacket,此時client端有三種反應:

1、client端連接正常,返回一個ACK.server端收到ACK后重置計時器,在2小時后在發送探測.如果2小時內連接上有數據傳輸,那么在該時間的基礎上向后推延2小時發送探測包;

2、客戶端異常關閉,或網絡斷開。client無響應,server收不到ACK,在一定時間(/proc/sys/net/ipv4/tcp_keepalive_intvl75 即75秒)后重發keepalive packet, 并且重發一定次數(/proc/sys/net/ipv4/tcp_keepalive_probes9 即9次);

3、客戶端曾經崩潰,但已經重啟.server收到的探測響應是一個復位,server端終止連接。

修改三個參數的系統默認值

臨時方法:向三個文件中直接寫入參數,系統重啟需要重新設置;

臨時方法:sysctl -w net.ipv4.tcp_keepalive_intvl=20

全局設置:可更改/etc/sysctl.conf,加上:

net.ipv4.tcp_keepalive_intvl = 20

net.ipv4.tcp_keepalive_probes = 3

net.ipv4.tcp_keepalive_time = 60

有關SO_KEEPALIVE的三個參數詳細解釋如下:

tcp_keepalive_intvl,保活探測消息的發送頻率。默認值為75s。

發送頻率tcp_keepalive_intvl乘以發送次數tcp_keepalive_probes,就得到了從開始探測直到放棄探測確定連接斷開的時間,大約為11min。

tcp_keepalive_probes,TCP發送保活探測消息以確定連接是否已斷開的次數。默認值為9(次)。

注意:只有設置了SO_KEEPALIVE套接口選項后才會發送保活探測消息。tcp_keepalive_time,在TCP保活打開的情況下,最后一次數據交換到TCP發送第一個保活探測消息的時間,即允許的持續空閑時間。默認值為7200s(2h)。

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/tcp.h>

int keepAlive = 1; // 開啟keepalive屬性

int keepIdle = 60; // 如該連接在60秒內沒有任何數據往來,則進行探測

int keepInterval = 5; // 探測時發包的時間間隔為5 秒

int keepCount = 3; // 探測嘗試的次數.如果第1次探測包就收到響應了,則后2次的不再發.

setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE,(void*)&keepAlive, sizeof(keepAlive));

setsockopt(rs, SOL_TCP,TCP_KEEPIDLE,(void*)&keepIdle, sizeof(keepIdle));

setsockopt(rs, SOL_TCP, TCP_KEEPINTVL,(void*)&keepInterval, sizeof(keepInterval));

setsockopt(rs, SOL_TCP, TCP_KEEPCNT,(void*)&keepCount, sizeof(keepCount));

?

?

4、??? 時間等待計時器

?

時間等待計時器是在四次握手的時候使用的。四次握手的簡單過程是這樣的:假設客戶端準備中斷連接,首先向服務器端發送一個FIN的請求關閉包(FIN=final),然后由established過渡到FIN-WAIT1狀態。服務器收到FIN包以后會發送一個ACK,然后自己由established進入CLOSE-WAIT。此時通信進入半雙工狀態,即留給服務器一個機會將剩余數據傳遞給客戶端,傳遞完后服務器發送一個FIN+ACK的包,表示我已經發送完數據可以斷開連接了,接著便進入LAST_ACK階段。客戶端收到以后,發送一個ACK表示收到并同意請求,接著由FIN-WAIT2進入TIME-WAIT階段。服務器端收到ACK,結束連接。此時(即客戶端發送完ACK包以后),客戶端還要等待2MSL(MSL=maxinumsegmentlifetime 最長報文生存時間,2MSL就是兩倍MSL)才能真正關閉連接。

等待2MSL是因為客服端發送的ACK對方可能沒有收到,1>此時服務端就要重FIN+ACK包,所以2MSL是從客服端發ACK對方沒有到然后服務端重發FIN+ACK的最長時間,等2MSL就是為了保證對方已經收到ACK包了。若不然,客戶端提早斷開的話服務器端一直重發FIN+ACK,永遠無法進入CLOSE狀態。

時間等待計時器就是用來記2MSL這個時間的,當計時器到了2MSL以后,客服端才能斷開連接。2>能夠保證之前某些在網絡中滯留很久的發給服務器的報文不會在本次連接連接關閉后再去騷擾服務器。 值得注意的是:最后兩次揮手期間,啟動了兩種計時器,服務器向客戶端發送FIN后啟動重傳計時器,客戶端收到FIN后,向服務器發送ACK,同時啟動Time-Wait計時器(時間長度為2MSL) 。

?

總結

以上是生活随笔為你收集整理的网络:TCP维护安全可靠机制提供的定时器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。