計算機網(wǎng)絡(luò)傳輸協(xié)議TCP三次握手與四次揮手原理
TCP三次握手四次揮手
我們之前在 傳輸層協(xié)議TCP與UDP 中詳細介紹了UDP協(xié)議和TCP協(xié)議格式以及他們各自的特點,我們知道TCP協(xié)議是面向連接的,那面向連接就得需要做建立連接,維護連接,斷開連接這些工作。
服務(wù)器狀態(tài)轉(zhuǎn)換
[CLOSED->LISTEN] 服務(wù)器調(diào)用listen后就進入LISTEN狀態(tài),等待客戶端向自己發(fā)起連接
[LISTEN->SYN_RCVD] 一旦監(jiān)聽到連接請求(同步報文段),就會將該連接放入內(nèi)核中維護的連接等待隊列中,并向客戶端發(fā)送SYN+ACK報文確認已收到看客戶端的連接請求
[SYN_RCVD->ESTABLISHED] 服務(wù)器一旦收到了客戶端的確認報文,就進入ESTABLISHED狀態(tài),就可以進行讀寫數(shù)據(jù)了
[ESTABLISHED->CLOSE_WAIT] 當客戶端主動關(guān)閉連接(調(diào)用close),服務(wù)器收到客戶端發(fā)送的結(jié)束報文段FIN,服務(wù)器向客戶端返回確認收到關(guān)閉連接的報文后,就會進入CLOSE_WAIT
[CLOSE_WAIT->LAST_ACK] 當服務(wù)器進入CLOSE_WAIT狀態(tài)時,說明服務(wù)器已經(jīng)開始準備關(guān)閉連接(但是需要先處理完之前的數(shù)據(jù)),當服務(wù)器真正調(diào)用close關(guān)閉連接時,會向客戶端發(fā)送FIN報文,自己則進入LAST_ACK狀態(tài),等待最后一個ACK的到來(這里的ACK是指客戶端對于服務(wù)器發(fā)送的FIN的響應(yīng)報文)
[LAST_ACK->CLOSED] 服務(wù)器收到了客戶端對FIN報文的響應(yīng)ACK,至此服務(wù)器關(guān)閉連接成功
客戶端狀態(tài)轉(zhuǎn)換
[CLOSED->SYN_SEND] 客戶端調(diào)用connect,向服務(wù)器發(fā)送同步報文段,表示想與服務(wù)器建立連接,自己進入SYN_SEND狀態(tài)等待服務(wù)器的響應(yīng)
[SYN_SEND->ESTABLISHED] connect調(diào)用成功,客戶端收到服務(wù)器的響應(yīng)報文ACK,進入ESTABLISHED狀態(tài),可以讀寫數(shù)據(jù)
[ESTABLISHED->FIN_WIAT_1] 客戶端主動調(diào)用close,向服務(wù)器發(fā)送結(jié)束報文段,自己進入FIN_WAIT_1狀態(tài),等待服務(wù)器的響應(yīng)
[FIN_WAIT_1->FIN_WAIT_2]客戶端收到服務(wù)器對結(jié)束報文段的確認,則進入FIN_WAIT_2狀態(tài),開始等待服務(wù)器的結(jié)束報文段
[FIN_WAIT_2 -> TIME_WAIT] 客戶端收到服務(wù)器發(fā)來的結(jié)束報文段, 進入TIME_WAIT, 并發(fā)出對服務(wù)器發(fā)送的結(jié)束報文的的響應(yīng) LAST_ACK;
[TIME_WAIT -> CLOSED] 客戶端要等待一個2MSL(Max Segment Life, 報文最大生存時間)的時間, 才會進入CLOSED狀態(tài)(因為要防止服務(wù)器沒有收到LASK_ACK,需要進行重發(fā)的情況).
TCP狀態(tài)轉(zhuǎn)換圖
TCP中常見的面試題
為什么是三次握手,不是一次或者兩次
答:3次握手完成兩個重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協(xié)商,這個序列號在握手過程中被發(fā)送和確認。
- 現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子,考慮計算機S和C之間的通信,假定C給S發(fā)送一個連接請求分組,S收到了這個分組,并發(fā)送了確認應(yīng)答分組。
按照兩次握手的協(xié)定,S認為連接已經(jīng)成功地建立了,可以開始發(fā)送數(shù)據(jù)分組。
可是,C在S的應(yīng)答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。
在這種情況下,C認為連接還未建立成功,將忽略S發(fā)來的任何數(shù)據(jù)分 組,只等待連接確認應(yīng)答分組。而S在發(fā)出的分組超時后,重復(fù)發(fā)送同樣的分組。這樣就形成了死鎖。 - 兩次握手還可能造成服務(wù)器資源的浪費,怎么說呢,再舉個栗子,假設(shè)今天C向S發(fā)送了一個連接請求,并等待S的響應(yīng),S給C發(fā)送ACK之后,就認為連接已經(jīng)建立,我們知道連接建立之后是需要維護這個連接的,此時S的操作系統(tǒng)就需要分配資源和空間來維護這個連接,那假設(shè)S給C的響應(yīng)丟失了,C并未收到響應(yīng)則認為連接沒有建立成功,不能正常通信,此時S維護的連接就是一個失敗的連接,不能成功通信,那假設(shè)今天由100萬個客戶端向S這個服務(wù)器發(fā)送連接請求,結(jié)果都沒有收到響應(yīng),此時S就維護了100萬個無用的連接,浪費服務(wù)器的資源
為什么是三次握手,四次揮手
答:因為當Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應(yīng)答的,SYN報文是用來同步的。
但是關(guān)閉連接時,當Server端收到FIN報文時,很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個ACK報文,告訴Client端,“你發(fā)的FIN報文我收到了”。
只有等到Server端所有的報文都發(fā)送完了,所有的數(shù)據(jù)也處理完了之后,Server端才能發(fā)送FIN報文表示自己能夠斷開連接,因此不能一起發(fā)送。故需要四步握手。
如果已經(jīng)建立了連接,但是客戶端突然出現(xiàn)故障了怎么辦?
答:TCP連接是有一個保活計時器,顯然,客戶端如果出現(xiàn)故障,服務(wù)器不能一直等下去,白白浪費資源。
服務(wù)器每收到一次客戶端的請求后都會重新復(fù)位這個計時器,時間通常是設(shè)置為2小時,若兩小時還沒有收到客戶端的任何數(shù)據(jù),服務(wù)器就會發(fā)送一個探測報文段,以后每隔75秒鐘發(fā)送一次。
若一連發(fā)送10個探測報文仍然沒反應(yīng),服務(wù)器就認為客戶端出了故障,接著就關(guān)閉連接。
為什么會有TIME_WAIT狀態(tài)
現(xiàn)在做一個測試,首先啟動server,然后啟動client,然后用Ctrl-C使server終止,這時馬上再運行server, 結(jié)果是:
這是因為,雖然server的應(yīng)用程序終止了,但TCP協(xié)議層的連接并沒有完全斷開,因此不能再次監(jiān) 聽同樣的server端口.我們用netstat命令查看一下:
- TCP協(xié)議規(guī)定,主動關(guān)閉連接的一方要處于TIME_ WAIT狀態(tài),等待兩個MSL(maximum segment lifetime)的時間后才能回到CLOSED狀態(tài).
- 我們使用Ctrl-C終止了server, 所以server是主動關(guān)閉連接的一方, 在TIME_WAIT期間仍然不能再次監(jiān)聽同樣的server端口;
- MSL在RFC1122中規(guī)定為兩分鐘,但是各操作系統(tǒng)的實現(xiàn)不同, 在Centos7上默認配置的值是60s;
- 可以通過
cat /proc/sys/net/ipv4/tcp_fin_timeout
查看msl的值
我們來想一想,為什么TIME_WAIT的時間是2MSL
MSL是TCP報文的最大生存時間, 因此TIME_WAIT持續(xù)存在2MSL的話就能保證在兩個傳輸方向上的尚未被接收或遲到的報文段都已經(jīng)消失(否則服務(wù)器立刻重啟, 可能會收到來自上一個進程的遲到的數(shù)據(jù), 但是這種數(shù)據(jù)很可能是錯誤的);
同時也是在理論上保證最后一個報文可靠到達(假設(shè)最后一個ACK丟失, 那么服務(wù)器會再重發(fā)一個FIN. 這時雖然客戶端的進程不在了, 但是TCP連接還在, 仍然可以重發(fā)LAST_ACK);
解決TIME_WAIT狀態(tài)引起的bind失敗的方法
- 在server的TCP連接沒有完全斷開之前不允許重新監(jiān)聽, 某些情況下可能是不合理的
- 服務(wù)器需要處理非常大量的客戶端的連接(每個連接的生存時間可能很短, 但是每秒都有很大數(shù)量的客戶端來請求).
- 這個時候如果由服務(wù)器端主動關(guān)閉連接(比如某些客戶端不活躍, 就需要被服務(wù)器端主動清理掉), 就會產(chǎn)生大量TIME_WAIT連接.
- 由于我們的請求量很大, 就可能導致TIME_WAIT的連接數(shù)很多, 每個連接都會占用一個通信五元組(源ip,源端口, 目的ip, 目的端口, 協(xié)議). 其中服務(wù)器的ip和端口和協(xié)議是固定的. 如果新來的客戶端連接的ip和端口號和TIME_WAIT占用的鏈接重復(fù)了,就會出現(xiàn)問題.
- 使用setsockopt() 設(shè)置socket描述符的 選項SO_REUSEADDR為1, 表示允許創(chuàng)建端口號相同但IP地址不同的多個socket描述符
- 加上了setsockopt之后,ctrl+c終止服務(wù)器之后也可以馬上啟動服務(wù)器
以上就是計算機網(wǎng)絡(luò)傳輸協(xié)議TCP三次握手與四次揮手原理的詳細內(nèi)容,更多關(guān)于TCP三次握手與四次揮手的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何在讀取Excel文件時創(chuàng)建列表的下拉菜單?
如何在讀取Excel文件時創(chuàng)建列表的下拉菜單?...2006-11-11