什么是計時器呢?我們可以理解成一塊鬧鍾,隔一段時間響一次,提醒TCP做特定的事情。TCP要正常工作,必須要有特定的計時器。那么TCP中有哪些計時器呢?
TCP中有四種計時器(Timer),分別為:
1.重傳計時器:Retransmission Timer
2.堅持計時器:Persistent Timer
3.保活計時器:Keeplive Timer
4.時間等待計時器:Timer_Wait Timer
(1)重傳計時器
大家都知道TCP是保證數據可靠傳輸的。怎么保證呢?帶確認的重傳機制。在滑動窗口協議中,接受窗口會在連續收到的包序列中的最后一個包向接收端發送一個ACK,當網絡擁堵的時候,發送端的數據包和接收端的ACK包都有可能丟失。TCP為了保證數據可靠傳輸,就規定在重傳的“時間片”到了以后,如果還沒有收到對方的ACK,就重發此包,以避免陷入無限等待中。
當TCP發送報文段時,就創建該特定報文的重傳計時器。可能發生兩種情況:
1.若在計時器截止時間到之前收到了對此特定報文段的確認,則撤銷此計時器。
2.若在收到了對此特定報文段的確認之前計時器截止時間到,則重傳此報文段,並將計時器復位。
(2)持久計時器
先來考慮一下情景:發送端向接收端發送數據包知道接受窗口填滿了,然后接受窗口告訴發送方接受窗口填滿了停止發送數據。此時的狀態稱為“零窗口”狀態,發送端和接收端窗口大小均為0.直到接受TCP發送確認並宣布一個非零的窗口大小。但這個確認會丟失。我們知道TCP中,對確認是不需要發送確認的。若確認丟失了,接受TCP並不知道,而是會認為他已經完成了任務,並等待着發送TCP接着會發送更多的報文段。但發送TCP由於沒有收到確認,就等待對方發送確認來通知窗口大小。雙方的TCP都在永遠的等待着對方。
要打開這種死鎖,TCP為每一個鏈接使用一個持久計時器。當發送TCP收到窗口大小為0的確認時,就堅持啟動計時器。當堅持計時器期限到時,發送TCP就發送一個特殊的報文段,叫做探測報文。這個報文段只有一個字節的數據。他有一個序號,但他的序號永遠不需要確認;甚至在計算機對其他部分的數據的確認時該序號也被忽略。探測報文段提醒接受TCP:確認已丟失,必須重傳。
堅持計時器的值設置為重傳時間的數值。但是,若沒有收到從接收端來的響應,則需發送另一個探測報文段,並將堅持計時器的值加倍和復位。發送端繼續發送探測報文段,將堅持計時器設定的值加倍和復位,直到這個值增大到門限值(通常是60秒)為止。在這以后,發送端每個60秒就發送一個探測報文,直到窗口重新打開。
(3)保活計時器
保活計時器使用在某些實現中,用來防止在兩個TCP之間的連接出現長時間的空閑。假定客戶打開了到服務器的連接,傳送了一些數據,然后就保持靜默了。也許這個客戶出故障了。在這種情況下,這個連接將永遠的處理打開狀態。
要解決這種問題,在大多數的實現中都是使服務器設置保活計時器。每當服務器收到客戶的信息,就將計時器復位。通常設置為兩小時。若服務器過了兩小時還沒有收到客戶的信息,他就發送探測報文段。若發送了10個探測報文段(每一個像個75秒)還沒有響應,就假定客戶除了故障,因而就終止了該連接。
這種連接的斷開當然不會使用四次握手,而是直接硬性的中斷和客戶端的TCP連接。
(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=maxinum segment lifetime最長報文生存時間,2MSL就是兩倍的MSL)才能真正的關閉連接。