經過如下的兩個例子清楚的瞭解三次握手和四次揮手的基本原理服務器
三次握手 >>>>舉個打電話的例子:網絡
A : 你好我是A,你聽獲得我在說話嗎併發
B : 聽到了,我是B,你聽到我在說話嗎計算機網絡
A : 嗯,聽到了server
創建鏈接,開始聊天!!!blog
這個網上轉載的例子不錯:資源
三次握手:
A:「喂,你聽獲得嗎?」A->SYN_SEND同步
B:「我聽獲得呀,你聽獲得我嗎?」應答與請求同時發出 B->SYN_RCVD | A->ESTABLISHED原理
A:「我能聽到你,今天balabala……」B->ESTABLISHEDcli
四次揮手:
A:「喂,我不說了。」A->FIN_WAIT1
B:「我知道了。等下,上一句還沒說完。Balabala…..」B->CLOSE_WAIT | A->FIN_WAIT2
B:」好了,說完了,我也不說了。」B->LAST_ACK
A:」我知道了。」A->TIME_WAIT | B->CLOSED
A等待2MSL,保證B收到了消息,不然重說一次」我知道了」,A->CLOSED
TCP是面向鏈接的,不管哪一方向另外一方發送數據以前,都必須先在雙方之間創建一條鏈接。在TCP/IP協議中,TCP 協議提供可靠的鏈接服務,鏈接是經過三次握手進行初始化的。三次握手的目的是同步鏈接雙方的序列號和確認號 並交換 TCP窗口大小信息。
1.第一次握手:創建鏈接。客戶端發送鏈接請求報文段,將SYN位置爲1,Sequence Number爲x;而後,客戶端進入SYN_SEND狀態,等待服務器的確認;
2.第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,須要對這個SYN報文段進行確認,設置Acknowledgment Number爲x+1(Sequence Number+1);同時,本身本身還要發送SYN請求信息,將SYN位置爲1,Sequence Number爲y;服務器端將上述全部信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時服務器進入SYN_RECV狀態;
3.第三次握手:客戶端收到服務器的SYN+ACK報文段。而後將Acknowledgment Number設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
完成了三次握手,客戶端和服務器端就能夠開始傳送數據。以上就是TCP三次握手的整體介紹。
那四次揮手呢?
當客戶端和服務器經過三次握手創建了TCP鏈接之後,當數據傳送完畢,確定是要斷開TCP鏈接的啊。那對於TCP的斷開鏈接,這裏就有了神祕的「四次揮手」。
1.第一次揮手:主機1(可使客戶端,也能夠是服務器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;
2.第二次揮手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number爲Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我也沒有數據要發送了,能夠進行關閉鏈接了;
3.第三次揮手:主機2向主機1發送FIN報文段,請求關閉鏈接,同時主機2進入CLOSE_WAIT狀態;
4.第四次揮手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,而後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段之後,就關閉鏈接;此時,主機1等待2MSL後依然沒有收到回覆,則證實Server端已正常關閉,那好,主機1也能夠關閉鏈接了。
至此,TCP的四次揮手就這麼愉快的完成了。當你看到這裏,你的腦子裏會有不少的疑問,不少的不懂,感受很凌亂;沒事,咱們繼續總結。
爲何要三次握手?
既然總結了TCP的三次握手,那爲何非要三次呢?怎麼以爲兩次就能夠完成了。那TCP爲何非要進行三次鏈接呢?在謝希仁的《計算機網絡》中是這樣說的:
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。
在書中同時舉了一個例子,以下:
"已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。"這就很明白了,防止了服務器端的一直等待而浪費資源。
爲何要四次揮手?
那四次揮手又是爲什麼呢?TCP協議是一種面向鏈接的、可靠的、基於字節流的運輸層通訊協議。TCP是全雙工 模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2, 它的數據已經所有發送完畢了;可是,這個時候主機1仍是能夠接受來自主機2的數據;當主機2返回ACK報文 段時,表示它已經知道主機1沒有數據發送了,可是主機2仍是能夠發送數據到主機1的;當主機2也發送了FIN 報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,以後彼此 就會愉快的中斷此次TCP鏈接。若是要正確的理解四次揮手的原理,就須要瞭解四次揮手過程當中的狀態變化。
FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等 待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態其實是當SOCKET在ESTABLISHED狀態時, 它想主動關閉鏈接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報 文後,則進入到FIN_WAIT_2狀態,固然在實際的正常狀況下,不管對方何種狀況下,都應該立刻迴應ACK 報文,因此FIN_WAIT_1狀態通常是比較難見到的,而FIN_WAIT_2狀態還有時經常能夠用netstat看到。 (主動方)
FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半鏈接,也即 有一方要求close鏈接,但另外還告訴對方,我暫時還有點數據須要傳送給你(ACK信息),稍後再關閉鏈接。 (主動方)
CLOSE_WAIT:這種狀態的含義實際上是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN 報文給本身,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實 際上你真正須要考慮的事情是察看你是否還有數據發送給對方,若是沒有的話,那麼你也就能夠 close這個 SOCKET,發送FIN報文給對方,也即關閉鏈接。因此你在CLOSE_WAIT狀態下,須要完成的事情是等待你去關 閉鏈接。(被動方)
LAST_ACK: 這個狀態仍是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報 文。當收到ACK報文後,也便可以進入到CLOSED可用狀態了。(被動方)
TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後便可回到CLOSED可用狀態了。 若是FINWAIT1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,能夠直接進入到TIME_WAIT狀態,而無 須通過FIN_WAIT_2狀態。(主動方)
CLOSED: 表示鏈接中斷。
爲何TCP協議終止連接要四次?
一、當主機A確認發送完數據且知道B已經接受完了,想要關閉發送數據口(固然確認信號仍是能夠發),就會發FIN給主機B。
二、主機B收到A發送的FIN,表示收到了,就會發送ACK回覆。
三、但這是B可能還在發送數據,沒有想要關閉數據口的意思,因此FIN與ACK不是同時發送的,而是等到B數據發送完了,纔會發送FIN給主機A。
四、A收到B發來的FIN,知道B的數據也發送完了,回覆ACK, A等待2MSL之後,沒有收到B傳來的任何消息,知道B已經收到本身的ACK了,A就關閉連接,B也關閉連接了。
A爲何等待2MSL,從TIME_WAIT到CLOSE?
在Client發送出最後的ACK回覆,但該ACK可能丟失。Server若是沒有收到ACK,將不斷重複發送FIN片斷。因此Client不能當即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK以後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。若是在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片斷在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。若是直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP鏈接。