TCP是什么?
TCP全稱是Transmission Control Protocol(傳輸控制協(xié)議)。在OSI(Open System Interconnect)模型(由七層組成,分別為物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會(huì)話層、表示層、應(yīng)用層)中屬于傳輸層,七層協(xié)議示意圖如下:

這樣分層是易于理解、學(xué)習(xí)和更新協(xié)議標(biāo)準(zhǔn)(更新某一層的協(xié)議,不會(huì)干擾到其他層),網(wǎng)絡(luò)分層,就像一個(gè)篩子,能快速定位故障發(fā)生的地方,更便于故障排除。
那傳輸層的主要作用是什么呢?傳輸層提供應(yīng)用程序間的通信。其功能包括:一、格式化信息流;二、提供可靠傳輸。為實(shí)現(xiàn)后者,傳輸層協(xié)議規(guī)定接收端必須發(fā)回確認(rèn),并且假如分組丟失,必須重新發(fā)送。
TCP是面向連接的協(xié)議,其顯著的特征是在傳輸之前需要3次握手形成會(huì)話。只有會(huì)話形成后,客戶端與服務(wù)端之間才能互相發(fā)送數(shù)據(jù)。
建立TCP連接的三次握手?
因?yàn)門CP協(xié)議是雙向通信的,不是一方向另一方單向通信,這就意味著雙方都具備有發(fā)送與接收的能力。那怎么確定都有發(fā)送與接收能力呢?
第一步:A向B請求連接,發(fā)送信息x,等待確認(rèn)(試探B的接收與發(fā)送能力)。(完成第一次握手)
第二步:B接收到A的消息后,確認(rèn)消息(ACK置為1,A具有發(fā)送能力),然后向A發(fā)送消息y請求連接(y是建立在x上的,試探A的接收能力)(完成第二次握手)
第三步:A接收到B的消息,確認(rèn)消息(ACK置為1,確認(rèn)B具有接收與發(fā)送的能力,A進(jìn)入establish狀態(tài)),然后發(fā)送B消息z(z是建立在y上的),B確認(rèn)消息(A具有接收能力,B進(jìn)入establish狀態(tài))(完成第三次握手)
這樣建立一個(gè)TCP連接,需要客戶端和服務(wù)端總共發(fā)送3個(gè)包(x、y、z)以確認(rèn)連接的建立。經(jīng)過這三次握手就能確定A與B都具備發(fā)送與接收的能力。圖解如下:

直白地表達(dá)這過程可以為:
Client:"Server,你能接收到我的消息嗎"
Server:"Client,我能接收到你的消息,你能接收我的消息嗎?"
Client:"Server,我也能接收到你的消息,我們開始聊聊今天會(huì)不會(huì)下雨"
Server:"Client,好的,今天會(huì)下雨哦,balabala..."
斷開TCP連接的四次揮手?
由于TCP連接時(shí)全雙工的,因此,每個(gè)方向都必須要單獨(dú)進(jìn)行關(guān)閉,那怎么確定兩個(gè)單獨(dú)都關(guān)閉了呢?
第一步:Client發(fā)送一個(gè)FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)。(第一次揮手)
第二步:Server收到FIN后,發(fā)送一個(gè)ACK給Client,確認(rèn)序號為收到序號+1(與SYN相同,一個(gè)FIN占用一個(gè)序號),Server進(jìn)入CLOSE_WAIT狀態(tài)。(第二次揮手)
第三步:Server發(fā)送一個(gè)FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK狀態(tài)。(第三次揮手)
第四步:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個(gè)ACK給Server,確認(rèn)序號為收到序號+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。(第四次揮手)
這樣斷開TCP連接需要四次揮手,如圖:

直白的類比:
男女票都要確認(rèn)對方微信下線
- 四次揮手
男票:"親愛的,這么晚了,不跟你聊了,我微信下線了啊"(男票處于等待狀態(tài),等待女票回復(fù))(第一次揮手)
女票:“親愛的,好吧”(批準(zhǔn)男票下線,女票也在準(zhǔn)備下線了)(第二次揮手)
(男票看到這個(gè)繼續(xù)等待,等待女票下線的信號)
女票:“那我也微信下線了”(女票告訴男票也要下線,這時(shí)女票處于等待狀態(tài),等待最后的確認(rèn),要讓男票也知道自己要下線了)(第三次揮手)
男票:“好的,下吧”(告訴女票知道了。確認(rèn)女票要下線了,安心了,男票下線!)(第四次揮手)
(女票看到確認(rèn)信息后,知道男票曉得自己要下線了,然后可以安心下線了!)
- 兩次揮手會(huì)怎么樣?
男票:"親愛的,這么晚了,不跟你聊了,我微信下線了啊"(男票處于等待狀態(tài),等待女票回復(fù))(第一次揮手)
女票:“親愛的,好吧”(批準(zhǔn)男票下線,女票也在準(zhǔn)備下線了)(第二次揮手)
此時(shí)男票看到后不管女票下不下線,不回復(fù),直接下線了(導(dǎo)致的結(jié)果是女票不要他了,不管我下不下線肯定不要)
- 三次揮手會(huì)怎么呀?
男票:"親愛的,這么晚了,不跟你聊了,我微信下線了啊"(男票處于等待狀態(tài),等待女票回復(fù))(第一次揮手)
女票:“親愛的,好吧”(批準(zhǔn)男票下線,女票也在準(zhǔn)備下線了)(第二次揮手)
女票:“那我也微信下線了”(女票告訴男票也要下線,這時(shí)女票處于等待狀態(tài),等待最后的確認(rèn),要讓男票也知道自己要下線了)(第三次揮手)
此時(shí)男票知道女票也會(huì)下線,安心了,然后下線了(導(dǎo)致的結(jié)果是女票還是不要他了,因?yàn)榕辈恢滥衅钡降卓吹搅藳],就下線了,要知道女票還在等回復(fù)呢)
- 五次揮手?
男票:"親愛的,這么晚了,不跟你聊了,我微信下線了啊"(男票處于等待狀態(tài),等待女票回復(fù))(第一次揮手)
女票:“親愛的,好吧”(批準(zhǔn)男票下線,女票也在準(zhǔn)備下線了)(第二次揮手)
(男票看到這個(gè)繼續(xù)等待,等待女票下線的信號)
女票:“那我也微信下線了”(女票告訴男票也要下線,這時(shí)女票處于等待狀態(tài),等待最后的確認(rèn),要讓男票也知道自己要下線了)(第三次揮手)
男票:“好的,下吧”(告訴女票知道了。確認(rèn)女票要下線了,安心了,男票下線!)(第四次揮手)
女票:“我看到了,那我們下線吧”(第五次揮手)
男票看到后,心想(看到了你下線啊,又要回復(fù)你,占用時(shí)間啊)要么直接下線(這是五次揮手,浪費(fèi)了時(shí)間,又不回復(fù)影響不好),要么再發(fā)確認(rèn)消息(這尼瑪要揮手多少次啊,還能不能下線了)
所以四次揮手是最合理的,哈哈(有不合理的可以在評論里噴噴,哈哈)
為什么連接的時(shí)候是三次握手,關(guān)閉的時(shí)候卻是四次握手?
因?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ā)送。故需要四步握手。