《TCP/IP具体解释》读书笔记(18章)-TCP连接的建立与中止
TCP是一個面向連接的協議。不管哪一方向還有一方發送數據之前。都必須在兩方之間建立一條連接。這樣的兩端間連接的建立與無連接協議UDP不同。UDP向還有一端發送數據報時,無需不論什么預告的握手。
1.建立連接的協議(3次握手)
1)請求端發送一個SYN段指明client打算連接的serverport,以及初始序列號。
2)server發回包含server的初始序號的SYN報文段作為應答。同一時候將確認序號設置為客戶的ISN加1以對客戶的SYN報文段進行確認。一個SYN將占用一個序號。
3)client將確認序號設置為server的ISN加1以對server的SYN報文段進行確認
ISN隨時間而變化。因此每一個連接都將具有不同的ISN。RFC793指出ISN能夠看作是一個32比特的計數器,每4ms加1。
這樣選擇序號的目的在于防止在網絡中被延遲的分組在以后又被傳送,而導致某個連接的一方對它作出錯誤的解釋。
2.連接終止協議
建立一個連接須要3次握手。為什么終止一個連接須要4次握手?這由TCP的半關閉造成的。既然一個TCP連接是全雙工(數據在兩個方向能同一時候傳遞),因此每一個方向必須單獨地進行關閉。
這原則就是當一方完畢它的數據發送后就能發送一個FIN來終止這個方向數據。當一端收到一個FIN。它必須通知應用層還有一端已經終止了那個方向的數據傳送。
收到FIN包意味著在這一方向上沒有數據流動(接收)。
一個TCP連接在收到一個FIN后仍能發送數據。
3.最大報文段長度
最大報文段長度(MSS)表示TCP傳往還有一端的最大數據長度(不包含20字節的IP首部和TCP首部)。當一個連接建立時。連接的兩方都要通告各自的MSS,MSS僅僅能出如今SYN報文段中。這是一個“協商”選項,并非強制性的。假設一方不接收來自還有一方的MSS值,則MSS默認值為536字節。MSS值一般為鏈路層的MTU減去20字節的IP首部和20字節的TCP首部. MSS = MTU - 40Byte
一般來說,假設沒有分段發生,MSS還是越大越好。報文段越大同意每一個報文段傳送的數據就越多,相對IP和TCP首部有更高的網絡利用率。
MSS讓主機限制還有一端發送數據報的長度。加上主機也能控制它發送數據報的長度。這將使以較小MTU連接到網絡上的主機避免分段。
4.TCP半關閉
TCP提供了連接的一端在結束它的發送后還能接收來自還有一端數據的能力。這就是所謂的半關閉。
當client發送FIN到服務端,服務端返回這個FIN的ACK后,并沒有向client發送FIN報文段,這段時間內就叫半關閉狀態。
此時client不能向服務端發送數據,但能夠接收服務端發送給它的數據。(書中有一個半關閉使用的樣例)
沒有半關閉。須要其他的一些技術讓client通知server,client已經完畢了它的數據傳送,但仍要接收來自server的數據。使用兩個TCP連接也能夠作為一個選擇。但使用半關閉的單連接更好。
5.TCP狀態變遷圖
5.1 這是一個看起來比較復雜的狀態遷移圖。由于它包含了兩個部分---server的狀態遷移和client的狀態變遷。
TCP正常連接建立和終止所相應的狀態。這11個狀態中較重要的部分,在以后的博文再進行解說。
5.2 2MSL等待狀態
TIME_WAIT狀態也稱為2MSL狀態。
每一個詳細TCP實現必須選擇一個報文段最大生存時間MSL,它是不論什么報文段被丟棄前在網絡內的最長時間,而這個時間是有限的。
當TCP運行主動關閉,并發回最后一個ACK。該連接必須在TIME_WAIT狀態停留2倍的MSL時間。這樣能夠讓TCP再次發送最后的ACK以防止這個ACK丟失(還有一端超時并重發最后的FIN)。
插口對(socket pair):(包含服務端ip。port和clientip,port的四元組)唯一確定每一個TCP連接。
這樣的2MSL等待的還有一個結果是這個TCP連接等待期間,定義這個連接的插口不能再被使用,這個連接僅僅能在2MSL結束才干再被使用。
在連接處于2MSL等待時,不論什么遲到的報文段將被丟棄,由于處于連接的插口不能被再用,因此當要建立一個有效的連接時,來自該連接的一個較早替身的遲到報文段作為新連接的一部分非常有可能被曲解。
如今問題來了,客戶運行主動關閉并進入TIME_WAIT是正常的。
server通常運行被動關閉不會進入TIME_WAIT狀態。這表明假設我們終止一個客戶程序,并馬上重新啟動這個客戶程序。則這個新客戶程序不能使用同樣的本地port,這不會帶來什么問題。由于客戶使用本地port,而并不關心這個port號是什么。
然而。對于server就存在問題,由于server使用熟知port。
假設我們終止一個已經建立連接的server程序,并試圖馬上重新啟動這個server程序。這個熟知port不能賦值給server程序。由于該port是處于2MSL連接的一部分。在重新啟動server程序前,它須要1~4分鐘。(假設我們一直試圖又一次啟動server程序,并測試它直到成功所需的時間,我們就能估算出2MSL值)
TCP實現加強了該限制,默認在2MSL等待狀態下,插口中使用的本地port也不能使用。但通過SO_REUSEADDR參數能夠重用該port。注意:2MSL狀態時該插口對不能使用是針對于主動關閉一方。 假如服務端主動關閉,然后用SO_REUSEADDR重用該port。假設直接用2MSL的插口對連接client將不會成功,但假設client使用插口對中的port來連接服務端。那么將是成功的,盡管該插口對還處于2MSL狀態。即同意一個連接到達仍處于2MSL狀態的連接。
5.3 平靜等待時間
對于來自某個連接的較早替身的遲到報文段。2MSL等待可防止將它解釋成使用同樣插口對的新連接的一部分。但這僅僅有在2MSL等待連接中的主機處于正常工作狀態時才有效。
假設使用2MSL等待的主機出現問題并在MSL內重新啟動。并馬上使用處于2MSL的插口對來建立一個新的連接,從而故障前發出而遲到的報文段會被錯誤地當作屬于重新啟動后新連接的報文段。
為了防止這樣的情況,RFC793提出TCP在重新啟動后的MSL秒內不能建立不論什么連接,這就是平靜等待時間(quiet time)。
僅僅有極少的實現版準遵守這一原則,由于大多數主機重新啟動時間的時間都比MSL秒要長。
5.3 FIN_WAIT_2狀態
主動關閉方已經發出了FIN。而且被動關閉方也已對它進行ACK確認,那么主動方進入FIN_WAIT_2狀態。僅僅有當被動方的進程完畢這個關閉(發出FIN包),主動方發出ack,主動方才從FIN_WAIT_2進入TIME_WATI狀態。
假設被動方一直不發出FIN包。這意味著主動和被動方分別永遠保持FIN_WAIT_2和CLOSE_WAIT狀態。并一直保持這個狀態直到應用層決定進行關閉。(很多伯克利實現採用下面方法來防止這樣的FIN_WAIT_2狀態的無限等待,假設運行主動關閉的應用層將進行全關閉,而不是半關閉,表示它不想接收數據,就設置一個定時器。假設這個連接空暇超過10分鐘75秒,那么TCP將進入CLOSED狀態)
6.復位報文段
連接不存在的port:
一般來說,不管何時一個報文段發往基準的連接出現錯誤,TCP都會發出一個復位報文段。
產生復位的一種常見情況是當連接請求到達時,目的port沒有進程正在監聽。比如當一個數據報達到目的port時,該port沒在使用。它將產生一個port不可達的信息,而TCP則使用復位。
異常終止一個連接:
終止連接有2個方式。當中一個是正常方式:一方發送FIN,也稱為有序釋放。正常情況下沒有不論什么數據丟失。但也有可能發送一個復位報文段而不是FIN來中途釋放一個連接,稱為異常釋放。
異常終止一個連接相應用程序來說有2個長處:
1)丟棄不論什么待發數據并馬上發送復位報文段
2)RST的接收方會區分還有一端運行的是異常關閉還是正常關閉。
須要注意的是RST報文段不會導致還有一端產生不論什么響應。還有一端根本不進行確認。收到RST的一方將終止連接,并通知應用層連接復位。
檢測半打開連接:
假設一方已經關閉或異常終止連接而還有一方卻還不知道。我們將這樣的TCP連接稱為半打開的(Half-Open)。
不論什么一端的主機異常都可能導致發生這樣的情況。僅僅要不打算在半打開連接上數據傳輸。仍處于連接狀態的一方就不會檢測還有一方已經出現異常。
半打開連接的還有一個常見原因是當客戶主機突然掉電而不是正常的結束客戶應用程序后再關機。此時假設server又又一次啟動,它將丟失復位前連接的全部信息。因此它不知道數據報文段中提到的連接。此時TCP處理的原則是接收方以復位作為應答。
7.同一時候打開
兩個應用程序同一時候彼此運行主動打開的情況是可能的。TCP特意設計能夠處理同一時候打開,對于同一時候打開它僅建立一條連接而不是兩條連接。
同一時候打開時,兩端差點兒同一時候發送SYN。并進入SYN_SENT狀態。
當每一端收到SYN時,狀態變為SYN_RCVD,同一時候它們都再發SYN并對收到的SYN進行確認。當兩方都收到SYN相應的ACK時。狀態都變遷為ESTABLISH。
一個同一時候打開的連接須要交換4個報文段。比正常的三次握手多1個,例如以下圖所看到的:
7.同一時候關閉
兩方同一時候運行主動關閉是可能的,TCP協議也同意這樣的同一時候關閉。
當應用層發出關閉命令時,兩端均從ESTABLISH變為FIN_WAIT1,這將導致兩方各發送一個FIN,兩個FIN經過網絡傳送后分別到達還有一端。收到FIN后。狀態由FIN_WAIT1變遷到CLOSING,并發達最后的ACK。狀態變化為TIME_WAIT。
同一時候關閉與正常關閉使用的段交換數據同樣。
8.TCPserver的設計
8.1 TCPserverport號:
TCPserver對于每一個連接都須要建立一個獨立的進程(或者是輕量級的。線程),來保證對話的獨立性。所以TCPserver是并發的。
當一個server進程接受一個來自client的請求時是怎樣處理port的?假設多個連接請求差點兒同一時候到達會發生什么情況?
1)首先使用neststat -a -n能夠查看網絡中的全部主機端。假定port號23為監聽port。在沒有不論什么請求連接時輸入命令能夠看到23port處于LISTEN監聽狀態。
(Foreign Address為*.*表示還不知道遠端IP地址和port號。由于該端還處于LISTEN狀態。正等待連接請求的到達)
2)從client發起一個服務端23port的連接,使用命令能夠看到處于LISTEN狀態的server進程仍然存在(23port)。用于接收其他的連接請求。當傳入的連接請求到達并被接收時,系統內核中的TCP模塊就創建一個處于ESTABLISHED狀態的端點(23port)。另外,處于ESTABLISHED狀態的連接port不會變化,也是23,與處于LISTEN狀態的進程同樣。
3)在使用port23的進程中,僅僅有處于LISTEN的進程能夠接收新的連接請求。
處于ESTABLISHED的進程將不能接收SYN報文段,而處于LISTEN的進程將不能接收數據報文段。
8.2 TCP處理呼入連接請求規則:
(1)正等待連接的一端有一個固定長度的連接隊列,該隊列中的連接已經完畢3次握手,但還沒有被應用層接收。
(2)應用層指定這個連接隊列的最大長度。這個值通常叫做積壓值(backlog)。取值范圍為0至5的整數。
(3)當一個請求連接到達(SYN),TCP依據連接隊列中的連接數確認是否接收這個連接,但這時的最大排隊連接數并不等于積壓值。
(4)假設連接隊列中的連接數少于最大排隊的連接數,TCP將確認建立連接。在client主動連接成功而服務端應用層還沒接收這個連接時。client發送的數據將保存在服務端的TCP緩存隊列。
(5)假設連接隊列沒有空間,TCP將丟棄收到的SYN請求。不發回不論什么報文(包含RST),client將超時重傳SYN請求,等待連接隊列有空間。
TCPserver無法使client的主動打開失效。由于server接收到請求時。TCP的三次握手已經完畢。所以對于限定遠程IP地址的server,必須在client三次握手建立連接后才干推斷是否合法。
作者原創,轉載請標明原處:http://blog.csdn.net/xifeijian/article/details/44250879
總結
以上是生活随笔為你收集整理的《TCP/IP具体解释》读书笔记(18章)-TCP连接的建立与中止的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android TV开发焦点动作控制小技
- 下一篇: Matlab Command Windo