網絡面試-0x11 TCP為什么需要三次握手和四次揮手凭涂?
一、三次握手
三次握手
[three-way-handshake]:客戶端和服務器總共發(fā)送3個包贴妻,以建立TCP連接切油。
什么是連接了?主要作用是什么名惩?
連接:
主要作用:為了確認雙方的接收能力
和發(fā)送能力
是否正常澎胡,指定自己的初始化序列號為后面的可靠性傳送做準備。
過程如下:
1)
第一次握手
:客戶端發(fā)送搞一個SYN報文給服務端娩鹉,并且報文中指明了客戶端的初始化系列seq=ISN(c),此時攻谁,客戶端處于SYN_SENT狀態(tài) 2)
第二次握手
:服務器收到客戶端的SYN包,處理之后弯予,發(fā)送自己的SYN+ACK包戚宦,將客戶端的ISN+1作為ack的值,此時锈嫩,服務器處于SYN_RCVD的狀態(tài)受楼。 3)
第三次握手
:客戶端發(fā)送一個ACK報文,seq=ISN+1呼寸。此時客戶端處于ESTABLISHED狀態(tài)艳汽。 服務器收到ACK報文之后,也處于ESTABLISHED狀態(tài)对雪,此時河狐,雙方已建立起了連接。 每次握手的作用:
第一次握手
:客戶端的發(fā)送能力慌植、服務器的接收能力是正常的甚牲。
第二次握手
:服務器的接收、發(fā)送能力正常蝶柿,客戶端的接收丈钙、發(fā)送能力是正常的。 不過交汤,此時服務器并不能確認客戶端的接收能力是否正常雏赦。
第三次握手
:客戶端接收劫笙、發(fā)送能力正常,服務器自己的發(fā)送星岗、接收能力也正常填大。
1、為什么不是兩次握手俏橘?
如果兩次握手允华,發(fā)送端能夠確定自己發(fā)送的信息對方能夠收到,而對方發(fā)送的消息寥掐,發(fā)送端也能夠收到靴寂。 接收端只能夠確定對方發(fā)送的消息自己能夠收到,而無法確定自己發(fā)送的消息對方能夠收到召耘。
2百炬、第2次握手傳回了ACK,為什么要穿SYN污它?
ACK 是告訴客戶端發(fā)來的數據已經接受無誤剖踊,而傳回SYN是為了把自己的初始化序列號seq同步給客戶端。
二衫贬、 四次揮手
TCP 終止一個連接德澈, 需要經過四次發(fā)包的過程。
揮手過程:
1)
第一次揮手
:客戶端發(fā)送一個FIN報文祥山,報文中指定一個序列號圃验。 此時,客戶端處于FIN_WAIT1狀態(tài)缝呕, 停止發(fā)送數據澳窑,等待服務端的確認。seq=x 2)
第二次揮手
:服務端接收到FIN報文之后供常,發(fā)送ACK報文摊聋, ack=x+1, seq=Y, 此時,服務端處于CLOSE_WAIT狀態(tài)栈暇。
3)
第三次揮手
:如果服務端也想斷開連接麻裁, 和客戶端的第一次揮手是一樣的,發(fā)送FIN報文源祈, 指定一個序列號煎源, 此時,服務器處于LAST_ACK的狀態(tài)香缺。4)
第四次揮手
:客戶端收到FIN之后手销,一樣發(fā)送一個ACK報文作為應答,且把服務器的序列號值+1作為自己ACK報文的序號值图张,此時客戶端處于TIME_WAIT狀態(tài)锋拖。需要過一陣子以確保服務端收到自己的ACK報文之后才會進入CLOSED狀態(tài)诈悍,服務端收到ACK報文之后,就處于關閉比連接了兽埃,處于CLOSED狀態(tài)侥钳。 1、 四次揮手原因
服務端在收到客戶端斷開連接FIN報文后柄错,并不會立即關閉連接舷夺, 而是先發(fā)送一個ACK包線告訴客戶端收到關閉連接的請求,只有當服務器的所有報文發(fā)送完畢之后售貌,才發(fā)送FIN報文斷開連接冕房,因此需要四次揮手。
2趁矾、CLOSE-WAIT 和 TIME-WAIT 的狀態(tài)和意義
CLOSE-WAIT
: 服務器收到客戶端關閉連接的請求并告訴客戶端自己已經成功收到了請求之后, 服務器進入CLOSE-WAIT狀態(tài)给僵,然而此時有可能服務端還有一些數據沒有傳輸完成毫捣,因此不能立即關閉連接, 而CLOSE-WAIT狀態(tài)就是為了保證服務器在關閉連接之前將待發(fā)送的數據發(fā)送完成帝际。
TIME-WAIT
:發(fā)生在第四次揮手蔓同,當客戶端收到那個服務端發(fā)送ACK確認報文后進入該狀態(tài),若取消該狀態(tài)蹲诀,即客戶端在收到服務端的FIN報文后立即關閉連接斑粱,此時,
(1)服務端相應的端口并沒有關閉脯爪,若客戶端在相同的端口立即建立了新的連接则北,則有可能接收到上次連接殘留的數據包,可能會導致不可以預料的異常出現痕慢∩写В—— 保證沒有收到殘余的數據
(2)除此之外,假設客戶端最后一次發(fā)送的ACK包在傳輸時候丟失掖举,由于TCP協議的超時重傳機制快骗,服務端將重發(fā)FIN報文,若客戶端并沒有維持TIME-WAIT狀態(tài)而直接關閉的話塔次,當收到服務端重新發(fā)送的FIN包時方篮,客戶端就會用RST包來響應服務端,這就會使得對方認為是有錯誤發(fā)生励负,然而其實只是正常的關閉連接過程藕溅,并沒有出現異常情況。 —— 保證最后一個ACK到達
3熄守、TIME-WAIT 狀態(tài)會導致什么問題蜈垮?怎么解決耗跛?
場景
: 高并發(fā)業(yè)務
在高并發(fā)短連接的TCP服務器上,當服務器處理完請求后攒发,主動請求關閉連接调塌,這樣服務器上會有大量的連接處于TIME_WAIT狀態(tài),服務器維護每個連接需要一個socket惠猿,也就是每個連接會占用一個文件描述符羔砾,而文件描述符的使用有上限的,如果持續(xù)高并發(fā)偶妖,會導致一些正常的連接失敗姜凄。
解決方案
:修改配置或設置SO_REUSEADDR套接字,使得服務器處于TIME-WAIT狀態(tài)下的端口能夠快速回收和重用趾访。
4态秧、TIME-WAIT為什么是2MSL?
當客戶端發(fā)出最后的ACK確認報文時扼鞋,并不能夠確定服務器端能夠接收到該段報文申鱼。 所以,此時會設置一個2MSL
的計時器云头。2MSL即是服務器端發(fā)出FIN報文和客戶端發(fā)出的ACK確認報文所能保持有效的最大時長捐友。
若是服務器沒有收到ACK報文,再次向客戶端發(fā)送FIN報文溃槐。 如果客戶端在2MSL內收到了服務器再次發(fā)來的FIN報文匣砖,說明服務器由于一些原因并沒有收到客戶端發(fā)出的ACK確認報文』璧危客戶端將再次向服務器發(fā)出ACK確認報文猴鲫,并重新開始2MSL計時。
所以:客戶端要經歷2MSL市場的TIME-WAIT階段谣殊,為的是確認服務器能否接收到客戶端發(fā)出的ACK確認報文变隔。
區(qū)分 MSL, TTL, RTT
1、MSL(Maximum Segment Lifetime) 報文最大生存空間蟹倾,任何報文在網絡上存在的最長時間匣缘,超過這個時間報文將被丟棄,因為TCP報文(segment)是IP數據報(datagram)的數據部分鲜棠。
每個具體的TCP實現都必須選擇一個確定的MSL值肌厨。RFC 1122建議是2分鐘。
2豁陆、TTL(time to live)生存時間柑爸。ip頭中有一個TTL域,這個生存時間是由源主機設置初始值但并不是存的具體時間盒音,而是存儲的一個IP數據報可以經過的最大路由數表鳍,每經過一個處理他的路由器此值就-1馅而,當此值位0則數據報將被丟棄,同時發(fā)送ICMP報文通知源主機譬圣。RFC 793中規(guī)定MSL為2分鐘瓮恭,實際應用中常用的是30秒,1分鐘和2分鐘等厘熟。
2MSL即兩倍的MSL屯蹦,TCP的TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài),當TCP的一端發(fā)起主動關閉绳姨,在發(fā)出最后一個ACK包后登澜,即第3次握手完成后發(fā)送了第四次握手的ACK包后就進入了TIME_WAIT狀態(tài),必須在此狀態(tài)上停留兩倍的MSL時間飘庄,等待2MSL時間主要目的是怕最后一個ACK包對方沒收到脑蠕,那么對方在超時后將重發(fā)第三次握手的FIN包,主動關閉端接到重發(fā)的FIN包后可以再發(fā)一個ACK應答包跪削。在TIME_WAIT狀態(tài)時兩端的端口不能使用空郊,要等到2MSL時間結束才可繼續(xù)使用。當連接處于2MSL等待階段時任何遲到的報文段都將被丟棄切揭。不過在實際應用中可以通過設置SO_REUSEADDR選項達到不必等待2MSL時間結束再使用此端口。
TTL與MSL是有關系的但不是簡單的相等關系锁摔,MSL要大于等于TTL廓旬。
3、RTT(round-trip time)客戶端到服務器往返所花的時間
谐腰。TCP含有動態(tài)估算RTT的算法孕豹。TCP還持續(xù)估算一個給定連接的RTT,這是因為RTT受網絡傳輸擁塞程序的變化而變化十气。
表示從發(fā)送端發(fā)送數據開始励背,到發(fā)送端收到來自接收端的確認(接收端收到數據后便立即發(fā)送確認),總共經歷的時延砸西。
一般認為單向時延=傳輸時延t1+傳播時延t2+排隊時延t3
t1是數據從進入節(jié)點到傳輸媒體所需要的時間叶眉,通常等于數據塊長度/信道帶寬
t2是信號在信道中需要傳播一定距離而花費的時間,等于信道長度/傳播速率(光纖中電磁波的傳播速率約為210^5 km/s芹枷,銅纜中2.310^5 km/s)
t3可籠統(tǒng)歸納為隨機噪聲衅疙,由途徑的每一跳設備及收發(fā)兩端負荷情況及吞吐排隊情況決定(包含互聯網設備和傳輸設備時延)
5、有很多TIME-WAIT狀態(tài)如何解決鸳慈?
服務器可以設置SO_REUSEADDR
套接字選項來通知內核饱溢,如果端口被占用,但 TCP 連接位于 TIME_WAIT 狀態(tài)時可以重用端口走芋。如果你的服務器程序停止后想立即重啟绩郎,而新的套接字依舊希望使用同一端口潘鲫,此時 SO_REUSEADDR 選項就可以避免 TIME-WAIT 狀態(tài)。
也可以采用長連接的方式減少 TCP 的連接與斷開肋杖,在長連接的業(yè)務中往往不需要考慮 TIME-WAIT 狀態(tài)溉仑,但其實在長連接的業(yè)務中并發(fā)量一般不會太高。
6兽愤、有很多CLOSE-WAIT狀態(tài)如何解決彼念?
1)檢查是不是自己的代碼問題(看是否服務端程序忘記關閉連接),如果是浅萧,則修改代碼
2)調整系統(tǒng)參數逐沙,包括句柄相關的參數和TCP/IP的參數,一般一個CLOSE_WAIT會維持至少2個小時的時間洼畅,我們可以通過調整參數來縮短這個時間吩案。
常見的關鍵縮寫:
CWR: 擁塞窗口減(發(fā)送方降低它的發(fā)送速率)
ECE: ECN會顯(發(fā)送方接收到一個更早的擁塞通告)
URG: 緊急(緊急指針字段有效 —— 很少被使用)
ACK: 確認(確認號字段有效 —— 連接建立以后,一般都啟用狀態(tài))
PSH:推送(接收方應盡快給應用程序傳送這個數據 —— 沒被可靠地實現或用到)
RST:重置連接(連接取消帝簇,經常是因為錯誤)
SYN:用于初始化一個連接的同步序號
FIN:該報文端發(fā)送方已經結束向對方發(fā)送數據徘郭。
三、 總結
公眾號:
技術小難
簡書
博客園 鏈接需要替換
CSDN
知乎
掘金
segmentfault
本文由mdnice多平臺發(fā)布