首先Client端發送鏈接請求報文,Server段接受鏈接後回覆ACK報文,併爲此次鏈接分配資源。Client端接收到ACK報文後也向Server段發生ACK報文,並分配資源,這樣TCP鏈接就創建了。緩存
最初兩端的TCP進程都處於CLOSED關閉狀態,A主動打開鏈接,而B被動打開鏈接。(A、B關閉狀態CLOSED——B收聽狀態LISTEN——A同步已發送狀態SYN-SENT——B同步收到狀態SYN-RCVD——A、B鏈接已創建狀態ESTABLISHED)服務器
B的TCP服務器進程先建立傳輸控制塊TCB,準備接受客戶進程的鏈接請求。而後服務器進程就處於LISTEN(收聽)狀態,等待客戶的鏈接請求。如有,則做出響應。
1)第一次握手:A的TCP客戶進程也是首先建立傳輸控制塊TCB,而後向B發出鏈接請求報文段,(首部的同步位SYN=1,初始序號seq=x),(SYN=1的報文段不能攜帶數據)但要消耗掉一個序號,此時TCP客戶進程進入SYN-SENT(同步已發送)狀態。
2)第二次握手:B收到鏈接請求報文段後,如贊成創建鏈接,則向A發送確認,在確認報文段中(SYN=1,ACK=1,確認號ack=x+1,初始序號seq=y),測試TCP服務器進程進入SYN-RCVD(同步收到)狀態;
3)第三次握手:TCP客戶進程收到B的確認後,要向B給出確認報文段(ACK=1,確認號ack=y+1,序號seq=x+1)(初始爲seq=x,第二個報文段因此要+1),ACK報文段能夠攜帶數據,不攜帶數據則不消耗序號。TCP鏈接已經創建,A進入ESTABLISHED(已創建鏈接)。
當B收到A的確認後,也進入ESTABLISHED狀態。網絡
第一次握手:起初兩端都處於CLOSED關閉狀態,Client將標誌位SYN置爲1,隨機產生一個值seq=x,並將該數據包發送給Server,Client進入SYN-SENT狀態,等待Server確認;
第二次握手:Server收到數據包後由標誌位SYN=1得知Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=x+1,隨機產生一個值seq=y,並將該數據包發送給Client以確認鏈接請求,Server進入SYN-RCVD狀態,此時操做系統爲該TCP鏈接分配TCP緩存和變量;
第三次握手:Client收到確認後,檢查ack是否爲x+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=y+1,而且此時操做系統爲該TCP鏈接分配TCP緩存和變量,並將該數據包發送給Server,Server檢查ack是否爲y+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client和Server就能夠開始傳輸數據。tcp
TCP 創建鏈接,其實經過兩次握手就能夠創建鏈接了,爲何要三次呢?是否是畫蛇添足呢?測試
一、《計算機網絡》中是這樣說的:操作系統
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。
在書中同時舉了一個例子,以下:
已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。」計算機網絡
二、網絡故障server
好比,如今網絡出現了故障,只能發請求數據包,而接收不到響應數據包,那麼只要發送一次請求,服務器就創建請求,這樣確定也是不對的,網絡請求有來有回才能完成通信。因此三次握手是必不可少的。blog
服務器端的資源分配是在二次握手時分配的,而客戶端的資源是在完成三次握手時分配的,因此服務器容易受到SYN洪泛攻擊,SYN攻擊就是Client在短期內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server則回覆確認包,並等待Client確認,因爲源地址不存在,所以Server須要不斷重發直至超時,這些僞造的SYN包將長時間佔用未鏈接隊列,致使正常的SYN請求由於隊列滿而被丟棄,從而引發網絡擁塞甚至系統癱瘓。隊列
假設Client端發起中斷鏈接請求,也就是發送FIN報文。Server端接到FIN報文後,意思是說"我Client端沒有數據要發給你了",可是若是你還有數據沒有發送完成,則沒必要急着關閉Socket,能夠繼續發送數據。因此你先發送ACK,"告訴Client端,你的請求我收到了,可是我還沒準備好,請繼續你等個人消息"。這個時候Client端就進入FIN_WAIT狀態,繼續等待Server端的FIN報文。當Server端肯定數據已發送完成,則向Client端發送FIN報文,"告訴Client端,好了,我這邊數據發完了,準備好關閉鏈接了"。Client端收到FIN報文後,"就知道能夠關閉鏈接了,可是他仍是不相信網絡,怕Server端不知道要關閉,因此發送ACK後進入TIME_WAIT狀態,若是Server端沒有收到ACK則能夠重傳。「,Server端收到ACK後,"就知道能夠斷開鏈接了"。Client端等待了2MSL後依然沒有收到回覆,則證實Server端已正常關閉,那好,我Client端也能夠關閉鏈接了。Ok,TCP鏈接就這樣關閉了!
數據傳輸結束後,通訊的雙方均可釋放鏈接,A和B都處於ESTABLISHED狀態。(A、B鏈接創建狀態ESTABLISHED——A終止等待1狀態FIN-WAIT-1——B關閉等待狀態CLOSE-WAIT——A終止等待2狀態FIN-WAIT-2——B最後確認狀態LAST-ACK——A時間等待狀態TIME-WAIT——B、A關閉狀態CLOSED)
1)A的應用進程先向其TCP發出鏈接釋放報文段(FIN=1,序號seq=u),並中止再發送數據,主動關閉TCP鏈接,進入FIN-WAIT-1(終止等待1)狀態,等待B的確認。
2)B收到鏈接釋放報文段後即發出確認報文段,(ACK=1,確認號ack=u+1,序號seq=v),B進入CLOSE-WAIT(關閉等待)狀態,此時的TCP處於半關閉狀態,A到B的鏈接釋放。
3)A收到B的確認後,進入FIN-WAIT-2(終止等待2)狀態,等待B發出的鏈接釋放報文段。
4)B沒有要向A發出的數據,B發出鏈接釋放報文段(FIN=1,ACK=1,序號seq=w,確認號ack=u+1),B進入LAST-ACK(最後確認)狀態,等待A的確認。
5)A收到B的鏈接釋放報文段後,對此發出確認報文段(ACK=1,seq=u+1,ack=w+1),A進入TIME-WAIT(時間等待)狀態。此時TCP未釋放掉,須要通過時間等待計時器設置的時間2MSL後,A才進入CLOSED狀態。
起初A和B處於ESTABLISHED狀態——A發出鏈接釋放報文段並處於FIN-WAIT-1狀態——B發出確認報文段且進入CLOSE-WAIT狀態——A收到確認後,進入FIN-WAIT-2狀態,等待B的鏈接釋放報文段——B沒有要向A發出的數據,B發出鏈接釋放報文段且進入LAST-ACK狀態——A發出確認報文段且進入TIME-WAIT狀態——B收到確認報文段後進入CLOSED狀態——A通過等待計時器時間2MSL後,進入CLOSED狀態。
TCP協議是一種面向鏈接的、可靠的、基於字節流的運輸層通訊協議。TCP是全雙工模式,這就意味着,當 Client 發出FIN報文段時,只是表示 Client 已經沒有數據要發送了,Client 告訴 Server,它的數據已經所有發送完畢了;可是,這個時候 Client 仍是能夠接受來自 Server 的數據;當 Server 返回ACK報文段時,表示它已經知道 Client 沒有數據發送了,可是 Server 仍是能夠發送數據到 Client 的;當 Server 也發送了FIN報文段時,這個時候就表示 Server 也沒有數據要發送了,就會告訴 Client ,我也沒有數據要發送了,以後彼此就會愉快的中斷此次TCP鏈接。若是要正確的理解四次分手的原理,就須要瞭解四次分手過程當中的狀態變化。
MSL最長報文段壽命Maximum Segment Lifetime,MSL=2
答:兩個理由:1)保證A發送的最後一個ACK報文段可以到達B。2)防止「已失效的鏈接請求報文段」出如今本鏈接中。
1)這個ACK報文段有可能丟失,使得處於LAST-ACK狀態的B收不到對已發送的FIN+ACK報文段的確認,B超時重傳FIN+ACK報文段,而A能在2MSL時間內收到這個重傳的FIN+ACK報文段,接着A重傳一次確認,從新啓動2MSL計時器,最後A和B都進入到CLOSED狀態,若A在TIME-WAIT狀態不等待一段時間,而是發送完ACK報文段後當即釋放鏈接,則沒法收到B重傳的FIN+ACK報文段,因此不會再發送一次確認報文段,則B沒法正常進入到CLOSED狀態。
2)A在發送完最後一個ACK報文段後,再通過2MSL,就可使本鏈接持續的時間內所產生的全部報文段都從網絡中消失,使下一個新的鏈接中不會出現這種舊的鏈接請求報文段。
答:由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。
答:雖然按道理,四個報文都發送完畢,咱們能夠直接進入CLOSE狀態了,可是咱們必須假象網絡是不可靠的,有能夠最後一個ACK丟失。因此TIME_WAIT狀態就是用來重發可能丟失的ACK報文。