TCP是傳輸層的協(xié)議损俭,傳輸層的協(xié)議主要負責為應用進程提供端到端的通信服務蛙奖。
TCP協(xié)議會以三次握手的形式來建立連接,所謂的“連接”杆兵,其實是客戶端和服務器的內存里保存的一份關于對方的信息雁仲,如ip地址、端口號等琐脏。
建立成功之后發(fā)送數(shù)據(jù)攒砖,發(fā)送數(shù)據(jù)結束之后,會以四次揮手的形式斷開連接日裙。
那么為什么要進行三次握手呢祭衩?
客戶端和服務端通信前要進行連接,“三次握手(Three-way Handshake)”的作用就是雙方都能明確自己和對方的收阅签、發(fā)能力是正常的掐暮。
第一次握手:客戶端發(fā)送網(wǎng)絡包,服務端收到了政钟。這樣服務端就能得出結論:客戶端的發(fā)送能力路克、服務端的接收能力是正常的。
第二次握手:服務端發(fā)包养交,客戶端收到了精算。這樣客戶端就能得出結論:服務端的接收、發(fā)送能力碎连,客戶端的接收灰羽、發(fā)送能力是正常的。 從客戶端的視角來看,我接到了服務端發(fā)送過來的響應數(shù)據(jù)包廉嚼,說明服務端接收到了我在第一次握手時發(fā)送的網(wǎng)絡包玫镐,并且成功發(fā)送了響應數(shù)據(jù)包,這就說明怠噪,服務端的接收恐似、發(fā)送能力正常。而另一方面傍念,我收到了服務端的響應數(shù)據(jù)包矫夷,說明我第一次發(fā)送的網(wǎng)絡包成功到達服務端,這樣憋槐,我自己的發(fā)送和接收能力也是正常的双藕。
第三次握手:客戶端發(fā)包,服務端收到了阳仔。這樣服務端就能得出結論:客戶端的接收忧陪、發(fā)送能力,服務端的發(fā)送驳概、接收能力是正常的赤嚼。 第一旷赖、二次握手后顺又,服務端并不知道客戶端的接收能力以及自己的發(fā)送能力是否正常。而在第三次握手時等孵,服務端收到了客戶端對第二次握手作的回應稚照。從服務端的角度,我在第二次握手時的響應數(shù)據(jù)發(fā)送出去了俯萌,客戶端接收到了果录。所以,我的發(fā)送能力是正常的咐熙。而客戶端的接收能力也是正常的弱恒。
經(jīng)歷了上面的三次握手過程,客戶端和服務端都確認了自己的接收棋恼、發(fā)送能力是正常的返弹。之后就可以正常通信了。
每次都是接收到數(shù)據(jù)包的一方可以得到一些結論爪飘,發(fā)送的一方其實沒有任何頭緒义起。我雖然有發(fā)包的動作,但是我怎么知道我有沒有發(fā)出去师崎,而對方有沒有接收到呢默终?
而從上面的過程可以看到,最少是需要三次握手過程的。兩次達不到讓雙方都得出自己齐蔽、對方的接收两疚、發(fā)送能力都正常的結論。其實每次收到網(wǎng)絡包的一方至少是可以得到:對方的發(fā)送肴熏、我方的接收是正常的鬼雀。而每一步都是有關聯(lián)的,下一次的“響應”是由于第一次的“請求”觸發(fā)蛙吏,因此每次握手其實是可以得到額外的結論的源哩。比如第三次握手時,服務端收到數(shù)據(jù)包鸦做,表明看服務端只能得到客戶端的發(fā)送能力励烦、服務端的接收能力是正常的,但是結合第二次泼诱,說明服務端在第二次發(fā)送的響應包坛掠,客戶端接收到了,并且作出了響應治筒,從而得到額外的結論:客戶端的接收屉栓、服務端的發(fā)送是正常的。
如果進行了兩次握手會怎樣耸袜?
如客戶端發(fā)出連接請求友多,但因連接請求報文丟失而未收到確認,于是客戶端再重傳一次連接請求堤框。后來收到了確認域滥,建立了連接。數(shù)據(jù)傳輸完畢后蜈抓,就釋放了連接启绰,客戶端共發(fā)出了兩個連接請求報文段,其中第一個丟失沟使,第二個到達了服務端委可,但是第一個丟失的報文段只是在某些網(wǎng)絡結點長時間滯留了,延誤到連接釋放以后的某個時間才到達服務端腊嗡,此時服務端誤認為客戶端又發(fā)出一次新的連接請求着倾,于是就向客戶端發(fā)出確認報文段,同意建立連接叽唱,不采用三次握手屈呕,只要服務端發(fā)出確認,就建立新的連接了棺亭,此時客戶端忽略服務端發(fā)來的確認虎眨,也不發(fā)送數(shù)據(jù),則服務端一直等待客戶端發(fā)送數(shù)據(jù),浪費資源嗽桩。
而且如果只進行兩次握手岳守,那么服務端無法確定自己的發(fā)送能力和客戶端的接收能力是正常的。
那么在這三次握手中碌冶,客戶端和服務端發(fā)送了什么呢湿痢?
SYN:synchronization(同步)
Seq:sequence(序列)
ACK:acknowledgment(回復,確認)
- 第一次握手:客戶端給服務端發(fā)一個 SYN 報文扑庞,并指明客戶端的初始化序列號 ISN(c)譬重。此時客戶端處于 SYN_SEND 狀態(tài)。
首部的同步位SYN=1罐氨,初始序號seq=x爽蝴,SYN=1的報文段不能攜帶數(shù)據(jù)堵未,但要消耗掉一個序號破衔。
第二次握手:服務器收到客戶端的 SYN 報文之后屈糊,會以自己的 SYN 報文作為應答,并且也是指定了自己的初始化序列號 ISN(s)租悄。同時會把客戶端的 ISN + 1 作為ACK 的值谨究,表示自己已經(jīng)收到了客戶端的 SYN,此時服務器處于 SYN_REVD 的狀態(tài)泣棋。
在確認報文段中SYN=1胶哲,ACK=1,確認號ack=x+1外傅,初始序號seq=y纪吮。
實際上加的數(shù)字不一定是1俩檬,但是會加一個數(shù)字萎胰。-
第三次握手:客戶端收到 SYN 報文之后,會發(fā)送一個 ACK 報文棚辽,當然技竟,也是一樣把服務器的 ISN + 1 作為 ACK 的值,表示已經(jīng)收到了服務端的 SYN 報文屈藐,此時客戶端處于 ESTABLISHED 狀態(tài)榔组。服務器收到 ACK 報文之后,也處于 ESTABLISHED 狀態(tài)联逻,此時搓扯,雙方已建立起了連接。
確認報文段ACK=1包归,確認號ack=y+1锨推,序號seq=x+1(初始為seq=x,第二個報文段所以要+1),ACK報文段可以攜帶數(shù)據(jù)换可,不攜帶數(shù)據(jù)則不消耗序號椎椰。
三次握手后建立連接,進行數(shù)據(jù)傳輸沾鳄,數(shù)據(jù)傳輸結束之后要進行四次揮手慨飘。
四次揮手
建立一個連接需要三次握手,而終止一個連接要經(jīng)過四次揮手(也有將四次揮手叫做四次握手的)译荞。這由TCP的半關閉(half-close)造成的瓤的。所謂的半關閉,其實就是TCP提供了連接的一端在結束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力吞歼。
TCP 的連接的拆除需要發(fā)送四個包堤瘤,因此稱為四次揮手(Four-way handshake),客戶端或服務器均可主動發(fā)起揮手動作浆熔。
剛開始雙方都處于 ESTABLISHED 狀態(tài)本辐,假如是客戶端先發(fā)起關閉請求。四次揮手的過程如下:
FIN:finish(結束)
- 第一次揮手:客戶端發(fā)送一個 FIN 報文医增,報文中會指定一個序列號慎皱。此時客戶端處于 FIN_WAIT1 狀態(tài)。
即發(fā)出連接釋放報文段(FIN=1叶骨,序號seq=u)茫多,并停止再發(fā)送數(shù)據(jù),主動關閉TCP連接忽刽,進入FIN_WAIT1(終止等待1)狀態(tài)天揖,等待服務端的確認。 - 第二次揮手:服務端收到 FIN 之后跪帝,會發(fā)送 ACK 報文今膊,且把客戶端的序列號值 +1 作為 ACK 報文的序列號值,表明已經(jīng)收到客戶端的報文了伞剑,此時服務端處于 CLOSE_WAIT 狀態(tài)斑唬。
即服務端收到連接釋放報文段后即發(fā)出確認報文段(ACK=1,確認號ack=u+1黎泣,序號seq=v)恕刘,服務端進入CLOSE_WAIT(關閉等待)狀態(tài),此時的TCP處于半關閉狀態(tài)抒倚,客戶端到服務端的連接釋放褐着。客戶端收到服務端的確認后托呕,進入FIN_WAIT2(終止等待2)狀態(tài)含蓉,等待服務端發(fā)出的連接釋放報文段洋访。 - 第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣谴餐,發(fā)給 FIN 報文姻政,且指定一個序列號。此時服務端處于 LAST_ACK 的狀態(tài)岂嗓。
即服務端沒有要向客戶端發(fā)出的數(shù)據(jù)汁展,服務端發(fā)出連接釋放報文段(FIN=1,ACK=1厌殉,序號seq=w食绿,確認號ack=u+1),服務端進入LAST_ACK(最后確認)狀態(tài)公罕,等待客戶端的確認器紧。 - 第四次揮手:客戶端收到 FIN 之后,一樣發(fā)送一個 ACK 報文作為應答楼眷,且把服務端的序列號值 +1 作為自己 ACK 報文的序列號值铲汪,此時客戶端處于 TIME_WAIT 狀態(tài)。需要過一陣子以確保服務端收到自己的 ACK 報文之后才會進入 CLOSED 狀態(tài)罐柳,服務端收到 ACK 報文之后掌腰,就處于關閉連接了,處于 CLOSED 狀態(tài)张吉。
即客戶端收到服務端的連接釋放報文段后齿梁,對此發(fā)出確認報文段(ACK=1,seq=u+1肮蛹,ack=w+1)勺择,客戶端進入TIME_WAIT(時間等待)狀態(tài)。此時TCP未釋放掉伦忠,需要經(jīng)過時間等待計時器設置的時間2MSL后省核,客戶端才進入CLOSED狀態(tài)。
收到一個FIN只意味著在這一方向上沒有數(shù)據(jù)流動缓苛》既觯客戶端執(zhí)行主動關閉并進入TIME_WAIT是正常的邓深,服務端通常執(zhí)行被動關閉未桥,不會進入TIME_WAIT狀態(tài)。
揮手為什么需要四次芥备?
因為TCP是全雙工通信的冬耿。
當服務端收到客戶端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文萌壳。其中ACK報文是用來應答的亦镶,SYN報文是用來同步的日月。
但是關閉連接時,當服務端收到FIN報文時缤骨,很可能并不會立即關閉SOCKET爱咬,所以只能先回復一個ACK報文,告訴客戶端绊起,"你發(fā)的FIN報文我收到了"精拟。只有等到我服務端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文虱歪,因此不能一起發(fā)送蜂绎。故需要四次揮手。
(1)第一次揮手笋鄙,當客戶端發(fā)送斷開連接的請求(即FIN報文)給服務端時师枣,僅僅代表客戶端不會再發(fā)送數(shù)據(jù)報文了,但客戶端仍可以接收數(shù)據(jù)報文萧落。
(2)第二次揮手践美,服務端此時有可能還有相應的數(shù)據(jù)報文需要發(fā)送,因此需要先發(fā)送ACK報文找岖,告知客戶端“我知道你想斷開連接的請求了”拨脉。這樣客戶端就不會因為沒有收到應答而繼續(xù)發(fā)送斷開連接的請求(即FIN報文)。
(3)第三次揮手宣增,服務端在處理完數(shù)據(jù)報文后玫膀,便發(fā)送給客戶端FIN報文;這樣可以保證數(shù)據(jù)通信正车ⅲ可靠地完成帖旨。發(fā)送完FIN報文后,服務端進入LAST_ACK階段(超時等待)灵妨。
(4)第四揮手解阅,如果客戶端及時發(fā)送ACK報文進行連接中斷的確認,這時服務端就直接釋放連接泌霍,進入可用狀態(tài)货抄。
當然,客戶端或服務器均可主動發(fā)起揮手動作朱转。