前言:相信有過面試經(jīng)歷的朋友們多多少少都會被問到經(jīng)典的TCP3次握手品嚣、4次揮手過程問題,為何看了網(wǎng)上博客千百遍钧大,即使當(dāng)時記住了過一段時間又忘記了翰撑?原因就在于你沒有真正的掌握,看死記硬背是不可能掌握的啊央,只有深入了解它的底層原理才算真正掌握眶诈,才能應(yīng)對面試官繼續(xù)深入的挖掘提問。這幾天為了徹底掌握TCP原理沒少花時間瓜饥,自覺得不敢說完全掌握逝撬,只是當(dāng)做學(xué)習(xí)筆記記錄下來,留給自己或者其他需要的人方便查看乓土。
其實(shí)3次握手和4次揮手宪潮,總結(jié)起來就一句話:為了確保TCP正確地建立連接和斷開連接
廢話不多說先看一下被看了無數(shù)遍的3次握手流程圖:
問:SYN、seq趣苏、ACK狡相、ack到底什么鬼,老是記不住
- 記住一點(diǎn)食磕,凡是大寫的尽棕,都叫標(biāo)記位(Flag),標(biāo)記位就是為了讓雙方知道此時的連接是請求連接芬为,還是請求的確認(rèn)萄金。
- 其他的小寫都是序號或確認(rèn)號蟀悦,代表發(fā)送數(shù)據(jù)具體的值媚朦。
-
SYN:請求號標(biāo)記位,當(dāng)
SYN=1日戈、ACK=0
時询张,表明這是一個建立連接的請求 。 - seq:序號浙炼,代表請求方將會發(fā)送的數(shù)據(jù)的第一個字節(jié)編號份氧。
-
ACK:確認(rèn)號標(biāo)記位,當(dāng)
ACK = 1
時弯屈,確認(rèn)號標(biāo)記字段才有效蜗帜。 - ack:返回的確認(rèn)號, 注意是小寫的资厉,代表 接收方 收到收據(jù)后(也就是前面說的seq)厅缺,這個確認(rèn)號代表 希望對方下一次傳輸數(shù)據(jù)的第一個字節(jié)編號
知道了上面的概念后我們再來詳細(xì)分析具體3尺握手流程
- 客戶端第一次發(fā)送一條連接請求數(shù)據(jù),
SYN = 1,ACK = 0
就是代表建立連接請求湘捎,發(fā)送的具體數(shù)據(jù)第一個字節(jié)編號記為x诀豁,賦值seq。 - 服務(wù)端收到請求后窥妇,返回 客戶端的
SYN = 1
,加上自己的確認(rèn)號ACK=1
,發(fā)送的具體數(shù)據(jù)第一個字節(jié)編號記為y舷胜,賦值seq,希望客戶端下一次返回編號x + 1個字節(jié)為止的數(shù)據(jù)活翩,記為ack = x + 1
烹骨。 - 客戶端收到服務(wù)端返回的請求確認(rèn)后,再次發(fā)送數(shù)據(jù)纱新,原封不動返回
ACK = 1
,這里就不需要再發(fā)送SYN=1
了展氓,為什么呢?因?yàn)榇藭r并不是跟服務(wù)端進(jìn)行連接請求脸爱,而是連接確認(rèn)遇汞,所以只需要返回ACK = 1
代表確認(rèn),同樣的簿废,發(fā)送的具體數(shù)據(jù)第一個字節(jié)編號記為seq = x + 1
空入,希望服務(wù)端下次傳輸?shù)臄?shù)據(jù)第一個字節(jié)編號記為ack = y + 1
擴(kuò)展:狀態(tài)解讀
- CLOSED: client處于關(guān)閉狀態(tài)
- LISTEN: server處于監(jiān)聽狀態(tài),等待client連接
- SYN-RCVD: 表示server接受到了SYN報文族檬,當(dāng)收到client的ACK報文后歪赢,它會進(jìn)入到ESTABLISHED狀態(tài)
- SYN-SENT: 表示client已發(fā)送SYN報文,等待server的第2次握手
- ESTABLISHED: 表示連接已經(jīng)建立
自以為學(xué)廢了单料?提問:為什么TCP建立連接時候埋凯,要進(jìn)行3次握手,2次不行嗎扫尖?
一句話的答案:主要目的:防止server端一直等待白对,浪費(fèi)資源
詳細(xì)解釋:
- 如果建立連接只需要2次握手,可能會出現(xiàn)的情況
- 假設(shè)client發(fā)出的第一個連接請求報文段换怖,因?yàn)榫W(wǎng)絡(luò)延遲甩恼,在連接釋放以后的某個時間才到達(dá)server 。
- 本來這是一個早已失效的連接請求沉颂,但server收到此失效的請求后条摸,誤認(rèn)為是client再次發(fā)出的一個新的連接請求 。
- 于是server就向client發(fā)出確認(rèn)報文段铸屉,同意建立連接
- 如果不采用“3次握手”钉蒲,那么只要server發(fā)出確認(rèn),新的連接就建立了 彻坛。
- 由于現(xiàn)在client并沒有真正想連接服務(wù)器的意愿顷啼,因此不會理睬server的確認(rèn)帆赢,也不會向server發(fā)送數(shù)據(jù) 。
- 但server卻以為新的連接已經(jīng)建立线梗,并一直等待client發(fā)來數(shù)據(jù)椰于,這樣,server的很多資源就白白浪費(fèi)掉了
- 采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生 仪搔,例如上述情況瘾婿,client沒有向server的確認(rèn)發(fā)出確認(rèn),server由于收不到確認(rèn)烤咧,就知道client并沒有要求建立連接偏陪。
一圖勝千言
問:第3次握手失敗了,會怎么處理?
- 此時server的狀態(tài)為SYN-RCVD煮嫌,若等不到client的ACK笛谦,server會重新發(fā)送SYN+ACK包
- 如果server多次重發(fā)SYN+ACK都等不到client的ACK,就會發(fā)送RST包昌阿,強(qiáng)制關(guān)閉連接
- 總結(jié):輪詢饥脑,多次沒有響應(yīng)關(guān)閉連接
四次揮手
一圖勝千言
FIN = 1:代表要求釋放連接
問:釋放連接為什么要4次?3次不行嗎懦冰?
- TCP是全雙工模式
- 第1次揮手:當(dāng)主機(jī)1發(fā)出FIN報文段時
- 表示主機(jī)1告訴主機(jī)2灶轰,主機(jī)1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是刷钢,此時主機(jī)1還是可以接受來自主機(jī)2的數(shù)據(jù)
- 第2次揮手:當(dāng)主機(jī)2返回ACK報文段時
- 表示主機(jī)2已經(jīng)知道主機(jī)1沒有數(shù)據(jù)發(fā)送了笋颤,但是主機(jī)2還是可以發(fā)送數(shù)據(jù)到主機(jī)1的
- 第3次揮手:當(dāng)主機(jī)2也發(fā)送了FIN報文段時
- 表示主機(jī)2告訴主機(jī)1,主機(jī)2已經(jīng)沒有數(shù)據(jù)要發(fā)送了
- 第4次揮手:當(dāng)主機(jī)1返回ACK報文段時
- 表示主機(jī)1已經(jīng)知道主機(jī)2沒有數(shù)據(jù)發(fā)送了内地。隨后正式斷開整個TCP連接
- 3次不行的原因就是要確保對方確實(shí)收到斷開連接的請求