【圖文講解】TCP為啥要3次握手和4次揮手?握兩次手不行嗎?
TCP有6種標(biāo)示:SYN(建立聯(lián)機(jī)) ACK(確認(rèn)) PSH(傳送) FIN(結(jié)束) RST(重置) URG(緊急)
一、TCP三次握手
第一次握手
客戶端向服務(wù)器發(fā)出連接請求報(bào)文,這時(shí)報(bào)文首部中的同部位SYN=1,同時(shí)隨機(jī)生成初始序列號(hào) seq=x
此時(shí),TCP客戶端進(jìn)程進(jìn)入了 SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定,SYN報(bào)文段(SYN=1的報(bào)文段)不能攜帶數(shù)據(jù),但需要消耗掉一個(gè)序號(hào)。
這個(gè)三次握手中的開始。表示客戶端想要和服務(wù)端建立連接。
第二次握手
TCP服務(wù)器收到請求報(bào)文后,如果同意連接,則發(fā)出確認(rèn)報(bào)文。確認(rèn)報(bào)文中應(yīng)該 ACK=1,SYN=1,確認(rèn)號(hào)是ack=x+1,同時(shí)也要為自己隨機(jī)初始化一個(gè)序列號(hào) seq=y
此時(shí),TCP服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD(同步收到)狀態(tài)。這個(gè)報(bào)文也不能攜帶數(shù)據(jù),但是同樣要消耗一個(gè)序號(hào)。這個(gè)報(bào)文帶有SYN(建立連接)和ACK(確認(rèn))標(biāo)志,詢問客戶端是否準(zhǔn)備好。
第三次握手
TCP客戶進(jìn)程收到確認(rèn)后,還要向服務(wù)器給出確認(rèn)。確認(rèn)報(bào)文的ACK=1,ack=y+1,此時(shí),TCP連接建立,客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)。
TCP規(guī)定,ACK報(bào)文段可以攜帶數(shù)據(jù),但是如果不攜帶數(shù)據(jù)則不消耗序號(hào)。這里客戶端表示我已經(jīng)準(zhǔn)備好。
思考:為什么要三次握手呢,有人說兩次握手就好了
舉例:已失效的連接請求報(bào)文段。
client發(fā)送了第一個(gè)連接的請求報(bào)文,但是由于網(wǎng)絡(luò)不好,這個(gè)請求沒有立即到達(dá)服務(wù)端,而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中滯留了,直到某個(gè)時(shí)間才到達(dá)server
本來這已經(jīng)是一個(gè)失效的報(bào)文,但是server端接收到這個(gè)請求報(bào)文后,還是會(huì)想client發(fā)出確認(rèn)的報(bào)文,表示同意連接。
假如不采用三次握手,那么只要server發(fā)出確認(rèn),新的建立就連接了,但其實(shí)這個(gè)請求是失效的請求,client是不會(huì)理睬server的確認(rèn)信息,也不會(huì)向服務(wù)端發(fā)送確認(rèn)的請求
但是server認(rèn)為新的連接已經(jīng)建立起來了,并一直等待client發(fā)來數(shù)據(jù),這樣,server的很多資源就沒白白浪費(fèi)掉了
采用三次握手就是為了防止這種情況的發(fā)生,server會(huì)因?yàn)槭詹坏酱_認(rèn)的報(bào)文,就知道client并沒有建立連接。這就是三次握手的作用。
二、TCP數(shù)據(jù)的傳輸過程
建立連接后,兩臺(tái)主機(jī)就可以相互傳輸數(shù)據(jù)了。如下圖所示:
1)主機(jī)A初始seq為1200,滑動(dòng)窗體為100,向主機(jī)B傳遞數(shù)據(jù)的過程。
2)假設(shè)主機(jī)B在完全成功接收數(shù)據(jù)的基礎(chǔ)上,那么主機(jī)B為了確認(rèn)這一點(diǎn),向主機(jī)A發(fā)送 ACK 包,并將 Ack 號(hào)設(shè)置為 1301。因此按如下的公式確認(rèn) Ack 號(hào):
Ack號(hào) = Seq號(hào) + 傳遞的字節(jié)數(shù) + 1
(這是在完全接受成功的情況下)
3)主機(jī)A獲得B傳來的ack(1301)后,開始發(fā)送seq為1301,滑動(dòng)窗體為100的數(shù)據(jù)。
……
與三次握手協(xié)議相同,最后加 1 是為了告訴對方要傳遞的 Seq 號(hào)。上面說了,主機(jī)B完全成功接收A發(fā)來的數(shù)據(jù)才是這樣的,如果存在丟包該如何。
下面分析傳輸過程中數(shù)據(jù)包丟失的情況,如下圖所示:
上圖表示通過 Seq 1301 數(shù)據(jù)包向主機(jī)B傳遞100字節(jié)的數(shù)據(jù),但中間發(fā)生了錯(cuò)誤,主機(jī)B未收到。
經(jīng)過一段時(shí)間后,主機(jī)A仍未收到對于 Seq 1301 的ACK確認(rèn),因此嘗試重傳數(shù)據(jù)。
為了完成數(shù)據(jù)包的重傳,TCP套接字每次發(fā)送數(shù)據(jù)包時(shí)都會(huì)啟動(dòng)定時(shí)器,如果在一定時(shí)間內(nèi)沒有收到目標(biāo)機(jī)器傳回的 ACK 包,那么定時(shí)器超時(shí),數(shù)據(jù)包會(huì)重傳。
上面也只是一種可能,比如數(shù)據(jù)1250丟失,那么Ack返回的就是1250,具體的可以詳細(xì)看下博客:
https://www.cnblogs.com/qdhxhz/p/10267932.html
三、TCP的四次揮手
第一次揮手
TCP發(fā)送一個(gè)FIN(結(jié)束),用來關(guān)閉客戶到服務(wù)端的連接??蛻舳诉M(jìn)程發(fā)出連接釋放報(bào)文,并且停止發(fā)送數(shù)據(jù)。
釋放數(shù)據(jù)報(bào)文首部,F(xiàn)IN=1,其序列號(hào)為seq=u(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加1),此時(shí),客戶端進(jìn)入FIN-WAIT-1(終止等待1)狀態(tài)。TCP規(guī)定,F(xiàn)IN報(bào)文段即使不攜帶數(shù)據(jù),也要消耗一個(gè)序號(hào)。
第二次揮手
服務(wù)端收到這個(gè)FIN,他發(fā)回一個(gè)ACK(確認(rèn)),確認(rèn)收到序號(hào)為收到序號(hào)+1,和SYN一樣,一個(gè)FIN將占用一個(gè)序號(hào)。
服務(wù)器收到連接釋放報(bào)文,發(fā)出確認(rèn)報(bào)文,ACK=1,ack=u+1,并且?guī)献约旱男蛄刑?hào)seq=v,此時(shí),服務(wù)端就進(jìn)入了CLOSE-WAIT(關(guān)閉等待)狀態(tài)。
TCP服務(wù)器通知高層的應(yīng)用進(jìn)程,客戶端向服務(wù)器的方向就釋放了,這時(shí)候處于半關(guān)閉狀態(tài),即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是服務(wù)器若發(fā)送數(shù)據(jù),客戶端依然要接受。
這個(gè)狀態(tài)還要持續(xù)一段時(shí)間,也就是整個(gè)CLOSE-WAIT狀態(tài)持續(xù)的時(shí)間。
客戶端收到服務(wù)器的確認(rèn)請求后,此時(shí),客戶端就進(jìn)入FIN-WAIT-2(終止等待2)狀態(tài),等待服務(wù)器發(fā)送連接釋放報(bào)文(在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù))。
第三次揮手
服務(wù)端發(fā)送一個(gè)FIN(結(jié)束)到客戶端,服務(wù)端關(guān)閉客戶端的連接。
服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報(bào)文,F(xiàn)IN=1,ack=u+1,由于在半關(guān)閉狀態(tài),服務(wù)器很可能又發(fā)送了一些數(shù)據(jù)
假定此時(shí)的序列號(hào)為seq=w,此時(shí),服務(wù)器就進(jìn)入了LAST-ACK(最后確認(rèn))狀態(tài),等待客戶端的確認(rèn)。
第四次揮手
客戶端發(fā)送ACK(確認(rèn))報(bào)文確認(rèn),并將確認(rèn)的序號(hào)+1,這樣關(guān)閉完成。
客戶端收到服務(wù)器的連接釋放報(bào)文后,必須發(fā)出確認(rèn),ACK=1,ack=w+1,而自己的序列號(hào)是seq=u+1,此時(shí),客戶端就進(jìn)入了TIME-WAIT(時(shí)間等待)狀態(tài)。
注意此時(shí)TCP連接還沒有釋放,必須經(jīng)過2??MSL(最長報(bào)文段壽命)的時(shí)間后,當(dāng)客戶端撤銷相應(yīng)的TCB后,才進(jìn)入CLOSED狀態(tài)。
服務(wù)器只要收到了客戶端發(fā)出的確認(rèn),立即進(jìn)入CLOSED狀態(tài)。同樣,撤銷TCB后,就結(jié)束了這次的TCP連接??梢钥吹剑?wù)器結(jié)束TCP連接的時(shí)間要比客戶端早一些。
思考:那么為什么是4次揮手呢?
為了確保數(shù)據(jù)能夠完成傳輸。
關(guān)閉連接時(shí),當(dāng)收到對方的FIN報(bào)文通知時(shí),它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了
所以你未必會(huì)馬上關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后,再發(fā)送FIN報(bào)文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了,所以它這里的ACK報(bào)文和FIN報(bào)文多數(shù)情況下都是分開發(fā)送的。
可能有人會(huì)有疑問,tcp我握手的時(shí)候?yàn)楹蜛CK(確認(rèn))和SYN(建立連接)是一起發(fā)送。揮手的時(shí)候?yàn)槭裁词欠珠_的時(shí)候發(fā)送呢?
因?yàn)楫?dāng)Server端收到Client端的SYN連接請求報(bào)文后,可以直接發(fā)送SYN+ACK報(bào)文。其中ACK報(bào)文是用來應(yīng)答的,SYN報(bào)文是用來同步的。
但是關(guān)閉連接時(shí),當(dāng)Server端收到FIN報(bào)文時(shí),很可能并不會(huì)立即關(guān)閉 SOCKET,所以只能先回復(fù)一個(gè)ACK報(bào)文,告訴Client端,"你發(fā)的FIN報(bào)文我收到了"。只有等到我Server端所有的報(bào)文都發(fā)送完了,我才能發(fā)送FIN報(bào)文,因此不能一起發(fā)送。故需要四步揮手。
思考:客戶端突然掛掉了怎么辦?
正常連接時(shí),客戶端突然掛掉了,如果沒有措施處理這種情況,那么就會(huì)出現(xiàn)客戶端和服務(wù)器端出現(xiàn)長時(shí)期的空閑。
解決辦法是在服務(wù)器端設(shè)置?;钣?jì)時(shí)器,每當(dāng)服務(wù)器收到客戶端的消息,就將計(jì)時(shí)器復(fù)位。超時(shí)時(shí)間通常設(shè)置為2小時(shí)。
若服務(wù)器超過2小時(shí)沒收到客戶的信息,他就發(fā)送探測報(bào)文段。若發(fā)送了10個(gè)探測報(bào)文段,每一個(gè)相隔75秒,還沒有響應(yīng)就認(rèn)為客戶端出了故障,因而終止該連接。
四、SYN(洪水)攻擊
背景
初始化連接的 SYN 超時(shí)問題Client發(fā)送SYN包給Server后掛了,Server回給Client的SYN-ACK一直沒收到Client的ACK確認(rèn),這個(gè)時(shí)候這個(gè)連接既沒建立起來,也不能算失敗。
這就需要一個(gè)超時(shí)時(shí)間讓Server將這個(gè)連接斷開,否則這個(gè)連接就會(huì)一直占用Server的SYN連接隊(duì)列中的一個(gè)位置,大量這樣的連接就會(huì)將Server的SYN連接隊(duì)列耗盡,讓正常的連接無法得到處理。
目前,Linux下默認(rèn)會(huì)進(jìn)行5次重發(fā)SYN-ACK包,重試的間隔時(shí)間從1s開始,下次的重試間隔時(shí)間是前一次的雙倍,5次的重試時(shí)間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發(fā)出后還要等32s都知道第5次也超時(shí)了
所以,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP才會(huì)把斷開這個(gè)連接。
由于,SYN超時(shí)需要63秒,那么就給攻擊者一個(gè)攻擊服務(wù)器的機(jī)會(huì),攻擊者在短時(shí)間內(nèi)發(fā)送大量的SYN包給Server(俗稱SYN flood攻擊),用于耗盡Server的SYN隊(duì)列。
什么是 SYN 攻擊
SYN 攻擊指的是,攻擊客戶端在短時(shí)間內(nèi)偽造大量不存在的IP地址,向服務(wù)器不斷地發(fā)送SYN包,服務(wù)器回復(fù)確認(rèn)包,并等待客戶的確認(rèn)。
由于源地址是不存在的,服務(wù)器需要不斷的重發(fā)直至超時(shí),這些偽造的SYN包將長時(shí)間占用未連接隊(duì)列,正常的SYN請求被丟棄,導(dǎo)致目標(biāo)系統(tǒng)運(yùn)行緩慢,嚴(yán)重者會(huì)引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓。SYN 攻擊是一種典型的 DoS攻擊。
如何檢測 SYN 攻擊?
檢測 SYN 攻擊非常的方便,當(dāng)你在服務(wù)器上看到大量的半連接狀態(tài)時(shí),特別是源IP地址是隨機(jī)的,基本上可以斷定這是一次SYN攻擊。在 Linux/Unix 上可以使用系統(tǒng)自帶的netstats 命令來檢測 SYN 攻擊。
如何防御 SYN 攻擊?
SYN攻擊不能完全被阻止,除非將TCP協(xié)議重新設(shè)計(jì)。我們所做的是盡可能的減輕SYN攻擊的危害,常見的防御 SYN 攻擊的方法有如下幾種:
縮短超時(shí)(SYN Timeout)
時(shí)間增加最大半連接數(shù)
過濾網(wǎng)關(guān)防護(hù)SYN
cookies技術(shù)
四、TCP和UDP的區(qū)別
我這里簡單列舉幾個(gè),因?yàn)槲疫€沒有研究UDP這個(gè)協(xié)議。
1、基于連接與無連接;UDP是無連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接
2、TCP保證數(shù)據(jù)正確性,UDP可能丟包,TCP保證數(shù)據(jù)順序,UDP不保證。
也就是說,通過TCP連接傳送的數(shù)據(jù),無差錯(cuò),不丟失,不重復(fù),且按序到達(dá);UDP盡最大努力交付,即不保證可靠交付Tcp通過校驗(yàn)和,重傳控制,序號(hào)標(biāo)識(shí),滑動(dòng)窗口、確認(rèn)應(yīng)答實(shí)現(xiàn)可靠傳輸。如丟包時(shí)的重發(fā)控制,還可以對次序亂掉的分包進(jìn)行順序控制。
3、UDP具有較好的實(shí)時(shí)性,工作效率比TCP高,適用于對高速傳輸和實(shí)時(shí)性有較高的通信或廣播通信。
4、每一條TCP連接只能是點(diǎn)到點(diǎn)的;UDP支持一對一,一對多,多對一和多對多的交互通信。
5、TCP對系統(tǒng)資源要求較多,UDP對系統(tǒng)資源要求較少。
作者:雨點(diǎn)的名字
https://www.cnblogs.com/qdhxhz/p/8470997.html
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:
長按訂閱更多精彩▼
如有收獲,點(diǎn)個(gè)在看,誠摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請聯(lián)系我們,謝謝!