TCP/IP協議
作者:Danbo 2015-7-2
本文為參考TCP/IP詳解卷一,某些知識點加上了作者自己的理解,如有錯誤,歡迎指正,可以微博聯系我!
TCP包格式和IP包格式如下:
TCP的正常建立與關閉
建立連接
TCP協議提供可靠的面向連接服務,采用三次握手建立連接。
第一次握手:建立連接時,客戶端發送SYN包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到SYN包,向客戶端返回ACK(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RCVD狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
完成三次握手,客戶端與服務器開始傳送數據,也就是ESTABLISHED狀態。
終止連接
采用四次揮手斷開雙向連接。
(1) TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送。
(2) 服務器收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
(3) 服務器關閉客戶端的連接,發送一個FIN給客戶端。
(4) 客戶端發回ACK報文確認,並將確認序號設置為收到序號加1。
TCP狀態變遷圖
客戶端的狀態可以用一下流程圖來表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務器的狀態可以流程圖:
CLOSED->LISTEN->SYN收到 ->ESTABLISHED->CLOSE_WAIT->LAST->ACK->CLOSED
2MSL等待狀態(兩個作用)
TIME_WAIT狀態也稱為2MSL等待狀態。每個具體TCP實現必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime)。它是任何報文段被丟棄前在網絡內的最長時間。處理原則:當TCP執行一個主動關閉,並發回最后一個ACK,該鏈接必須在TIME_WAIT狀態停留的時間為2MSL。這樣可讓TCP有機會在此發送最后一個ACK以防這個ACK丟失(在另一端發送FIN前提)
但是,在連接處於2MSL等待時,任何遲到返回的報文段將被丟棄。因為處於2MSL等待的、由該插口對(socket pair)定義的連接在這段時間內不能被再用,對於客戶程序還好 一些,但是對於服務程序,例如httpd,它總是要使用同一個端口80來進行服務,而在 2MSL時間內,啟動httpd就會出現錯誤(插口被使用)。為了避免這個錯誤,服務器給出了一個平靜時間(quit time)的概念,這是說在2MSL時間內,雖然可以重新啟動服務器,但是這個服務器還是要平靜等待MSL時間才能進行下一次連接,讓后來返回的數據包沒有機會影響到發送端,因為返回的包和重新建立的包使用同一個四元組,發送端無法區分這兩個包屬於不同連接。(建議MSL時間為2min,不過這個與操作系統有關。)
半打開狀態(Half-Open)
如果以防已經關閉或異常終止連接而另一方卻不知道,我們將這樣的TCP連接稱為半打開的。這種狀態可以通過Keepalive選項來進行發現兩一段已經消失。還有一種形式是:本端發送SYN,對端回應ACK+SYN,此時本段不回應ACK。
當處於半打開狀態的一方重啟並重新連接后,它將丟失復位前的所有信息,因此它並不知道數據報文段中提到的連接。此時就會返回RST(異常終止要發送RST置位的包)包應答,已關閉此次連接。此時只需要等待MSL時間,因為TCP默認機器重啟的時間大於MSL。PIX防火牆和IDS入侵檢測系統都可以偽裝攻擊目標發送RST的包去終止異常的TCP連接。(比如限定連接的時間,減少半開連接限制超時時間)當我們Telnet一個不存在的端口號時,本段立馬收到一個拒絕訪問的包,這個就是對方發送的RST包導致的。
半關閉狀態(Half-Close)
單方向鏈路關閉。即TCP連接一端在結束它的發送后還能接收來自另一端數據的能力。程序調用的是shutdown,而不是close,不過大多數程序都是調用close終止兩個方向的連接。
最大報文段長度MSS(Option字段)
最大報文段長度表示TCP傳往另一端的最大塊數據的長度。當建立一個連接時,每一方都受到對方通告的MSS值(MSS選項只能出現在SYN報文中)。如果一方收不到另一方的MSS值,那么就設為默認的536字節。MSS是最長見的選項字段,還有另一個選項叫做窗口放大因子(Window*Shift Count即可以發送超大的數據包,即乘以目前窗口的倍數為實際一次發送的數據量。解決高速鏈路和高速主機普通TCP發包過慢問題。)。還有一些HASH值也會放在Option字段。而防火牆默認則會清掉IP和TCP的Option選項字段。
納格算法
經受時延的確認
一個例子:這里我們將舉另外一個例子:在一個交互注冊過程中鍵入中斷的一個特殊功能鍵。這個功能鍵通常可以產生多個字符序列,經常從ASCII碼的轉移(escape)字符開始,如果TCP每次得到一個字符,它很可能會發送序列中的第一個字符(ASCII碼的ESC),然后緩存其他字符並等待對該字符的確認。但當服務器收到該字符后,它並不發送確認而是繼續的等待接受序列中的其他字符。這就會經常觸發服務器的經受時延的確認算法,表示剩下的字符沒有在200ms內發送。對於交互用戶而言,這將產生明顯的時延。
注意只有客戶端這邊有經受時延的確認,因為客戶端這邊輸入的比較慢,服務器那邊收到數據就會立即確認。最大等待200ms還沒有數據發送的話,客戶端就直接返回ACK了。
滑動窗口
TCP采用滑動窗口來進行傳輸控制,滑動窗口的大小意味着接收方有多大的緩存區可以用於接收數據。發送方可以通過滑動窗口的大小來確定應該發送多少字節的數據。當滑動窗口為0時,發送方一般不能再發送數據,但是緊急數據除外,例如:允許用戶終止在遠端機上的運行進程。另一種情況是發送方可以發送一個1字節的數據報來通知接收方重新聲明它希望接收的下一字節及發送方的滑動窗口大小。
滑動窗口機制的基本原理就是在任意時刻,發送方都維持了一個連續的允許發送的幀的序號,稱為發送窗口,同時,接收方也維持了一個允許接收的幀的序號,稱為接收窗口。發送窗口和接收窗口的序號的上下界不一定要一樣,甚至大小也可不同。不同的滑動窗口協議窗口大小一般不同。發送窗口內的序號的上下界不一定要一樣,但是還沒有被確認的幀,或者是哪些可以被發送的幀。
- 稱窗口左邊向右邊靠近為窗口合攏。這種現象發生在數據被發送和確認時。
- 當窗口右邊沿想右移動時將允許發送更多的數據,我們稱之為窗口張開。這種先發發送在另一端的接收進程讀取已經確認的數據並釋放了TCP的接收緩存時。
- 當右邊裝口左移時,我們稱之為窗口收縮。
發送方打開幾號窗口表示發送方已經發送了該序列的幀,但是如果沒有得到接收方ack確認的話,此時該序號的幀仍然在發送窗口中。接收方方打開幾號窗口代表接收端收到幾號的幀,但是並沒有返回ack確認。當接收方返回該序號的ack時,該序號關閉(合攏),接收方收到ack時,該序號窗口關閉(此時窗口張開,注意始終不能大於通告窗口大小)。
對於發送窗口來說窗口打開代表發送了該序列數據,但沒有收到確認,收到ACK后窗口合攏。
對於接受窗口來說窗口打開代表接受了該序列數據,但沒有發送確認,當發ACK后窗口合攏。
1比特滑動窗口協議
當發送窗口和接收窗口的大小固定為1時,滑動窗口協議退化為停等協議(stop-and-wait)。該協議規定發送方每發送一幀后就要停下來,等待接收方已正確接收的確認(Acknowledgement)返回后才能繼續發送下一個幀。由於發送方需要判斷接收到的幀是新習發的幀還是重新發送的幀,因此發送放要為每個幀加一個序號。由於停等協議規定只要一幀完全發送成功后才能發送新的幀,因而只用一比特來編號就夠了。
后退n協議
由於停等協議要為每一個幀進行確認后才繼續發送下一幀,大大降低了信道利用率,因此又提出了后退n協議。后退n協議中,發送方在發完已給數據幀后 ,不停下來等待應答幀,而是連續發送若干個幀,即使在連續發送過程中收到了接收方發來的應答幀,也可以繼續發送。且發送方在每發完一個數據幀時都要設置超時定時器。只要在所設置的超時時間內未收到確認幀,就要重發相應的數據幀。如:當發送方發送了N個幀后,若發現該N幀的前一個幀在計時器超后仍未返回其確認信息,該幀被判定為出錯或者丟失,此時發送方就不得不重新發送出錯幀及其后的N幀。
從這里不難看出,后退n協議一方面因連續發送數據幀而提高了效率,但是另一方面,在重傳時又必須把原已正確重傳的數據幀進行重傳(僅因這些數據這之前有一個數據幀出錯),這種做法又使重傳效率降低。由此可見,若傳輸信道的傳輸質量很差因而導致誤碼率較大,連續測協議不一定優於停止等待協議。此協議中的發送窗口的大小為k,接收窗口仍未1.
選擇重傳協議
在后退n協議中,接收方若發現錯誤幀就不再接收后續的幀,及時是正確的幀到達,這顯然是一種浪費。另一種效率跟高的策略是當接收方發現某幀出錯后,其后繼續送來的正確的幀雖然不能立即遞交給接收方的高層,但接收方扔可收下來,存放在一個緩沖區,同時要求發送方重新傳輸出錯的那一幀。一旦收到重新傳來的幀后,就可以源存與緩沖區中國的其余幀一並按正確的順序遞交高層。這種方法稱為選擇重發(Selectice Repeat),顯然,選擇重發減少了浪費,但要求接收方有足夠大的緩沖區空間。
糊塗窗口綜合症
慢啟動
TCP超時與重傳
擁塞避免算法

快速重傳與快速恢復算法

TCP堅持定時器
TCP保活定時器
版權聲明:本文為博主原創文章,未經博主允許不得轉載。