TCP三次握手,握的是啥?
目錄
前言
先要弄清楚兩個概念
抓包分析
建立連接過程中的Sequence number
數(shù)據(jù)傳輸過程中的Sequence number
為什么TCP建立連接不是兩次握手也不是四次握手?
補充閱讀
前言
最近在知乎上看到一個問題——TCP為什么是三次握手,而不是兩次或四次?這個問題我原先也發(fā)過博客,之前我的回答是:為了防止兩次握手情況下已失效的連接請求報文段突然有傳送到服務(wù)端,而產(chǎn)生了錯誤(主要是參考謝希仁版的《計算機網(wǎng)絡(luò)》)。以及四次握手不能有效的增加TCP連接的安全性,反而讓客戶端等待的時間變長。但是在看了車小胖的回答后,我才真的理解了為什么TCP連接要采用三次握手以及三次握手握了哪些信息。以下會有很多他所舉得例子,我也會抓一些包向大家展示三次握手中的序號和確認號的變化。而謝希仁版的《計算機網(wǎng)絡(luò)》給我們的例子也沒有問題,只是問題的切入點不一樣。
?
先要弄清楚兩個概念
(1) 序號:占4個字節(jié)。TCP是面向字節(jié)流的,所以TCP連接中傳送的數(shù)據(jù)流中的每一個字節(jié)都編上一個序號。序號字段的值則指的是本報文段所發(fā)送的數(shù)據(jù)的第一個字節(jié)的序號。例如,一個報文段的序號字段值是200,攜帶的數(shù)據(jù)總共有100字節(jié),表明這個報文段的數(shù)據(jù)的最后一個字節(jié)的序號是299,所以下一個報文段的數(shù)據(jù)序號應(yīng)從300開始。
(2) 確認號:占4個字節(jié),是期望收到對方的下一個報文段的數(shù)據(jù)的第一個字節(jié)的序號。若確認號為N,表明前N-1的所有數(shù)據(jù)都已經(jīng)正確接收。例如,B正確的收到了A發(fā)送過來的一個報文段,其序號字段是指501,而數(shù)據(jù)長度是200字節(jié)(序號501~700),表明B正確的收到了A發(fā)送的序號700之前的數(shù)據(jù)。因此B希望收到A的下一個數(shù)據(jù)序號是701,所以B在發(fā)送給A的確認報文段中應(yīng)把確認號設(shè)置成701。
TCP可靠傳輸?shù)木?#xff1a;TCP連接的一方A,由操作系統(tǒng)動態(tài)隨機選取一個32位長的序列號(Initial Sequence Number),假設(shè)A的初始序列號為1000,以該序列號為起始點,對自己將要發(fā)送的每個字節(jié)的數(shù)據(jù)進行編號,1000,1001,1002,1003…,并把自己的初始序列號ISN告訴B,讓B有一個思想準備,什么樣編號的數(shù)據(jù)是合法的,什么編號是非法的,比如編號900就是非法的,同時B還可以對A每一個編號的字節(jié)數(shù)據(jù)進行確認。如果A收到B確認編號為2000,則意味著字節(jié)編號為1000-1999,共1000個字節(jié)已經(jīng)安全到達。
同理B也是類似的操作,假設(shè)B的初始序列號ISN為2000,以該序列號為原點,對自己將要發(fā)送的每個字節(jié)的數(shù)據(jù)進行編號,2000,2001,2002,2003…,并把自己的初始序列號ISN告訴A,以便A可以確認B發(fā)送的每一個字節(jié)。如果B收到A確認編號為4000,則意味著字節(jié)編號為2000-3999,共2000個字節(jié)已經(jīng)安全到達。
?
一句話概括,TCP連接握手,握的是啥?
通信雙方數(shù)據(jù)的序列號的起始點!
?
抓包分析
建立連接過程中的Sequence number
圖中的[1687]和[1688]是三次握手中的后兩步。從[1687]這個報文可以看到Sequence number的值為0,但是下方相應(yīng)報文段的內(nèi)容是[7f ?a6 ?f7 ?31]。
?
[1688]的Sequence number值為1,但是下方相應(yīng)報文段的內(nèi)容是[12 ?2d ?d7 ?1d](起始點)。
?
[8197]發(fā)送的確認報文Sequence number為10147,即有[12 ?2d ?fe ?bf](65215) - [12 ?2d ?d7 ?1d](55069) = 10147 - 1。這說明在三次握手的過程中,通信雙方就將自己的序號的起始點告知給了對方,并且對方將這個數(shù)字記錄了下來,用于之后的通信。此時報文段中的實際值不代表傳輸過程中的序號值的真實含義。
?
為什么TCP在建立連接的時候不能每次選擇相同的、固定的初始序號?
答:(1)假如A和B頻繁地建立連接,傳送一些TCP報文段后再釋放連接,然后又不斷的建立新的連接、傳送報文段和釋放連接。
(2)假如每一次建立連接時,主機A都選擇相同的、固定的初始序號,如1。
(3)若主機A發(fā)送出的某些TCP報文段在網(wǎng)絡(luò)中會滯留較長的時間,以致造成主機A超時重傳這些TCP報文段。
(4)若有一些在網(wǎng)絡(luò)中滯留時間較長的TCP報文段最后終于到達了主機B,但這時傳送該報文段的那個連接早已釋放了,而在到達主機B時的TCP連接是一條新的TCP連接。
以上這些情況可能會導致在新的TCP連接中的主機B有可能會接收在舊的連接傳送的、已經(jīng)沒有意義的、過時的TCP報文段(因為這個TCP報文段的序號有可能正好處于新的連接所使用的序號范圍內(nèi))。因為必須使得遲到的TCP報文段的序號不在新的連接中使用的序號范圍內(nèi)。所以,TCP在建立新的連接時所選擇的初始序號一定要和前面的一些連接所使用過的序號不一樣。因此,不同的TCP連接不能使用相同的初始序號。
?
數(shù)據(jù)傳輸過程中的Sequence number
以下用A代表客戶端,B代表服務(wù)器。
[8197]A->B ?Seq = 10147 ?Ack = 10391980 ?Len = 0 ??沒有傳輸數(shù)據(jù),希望下一個收到的報文段的序號為10391980。
[8198]B->A ?Seq = 10391980 ?Ack = 10147 ?Len = 2800 ??因為[8197]沒有數(shù)據(jù),所以B希望收到的序號還是10147。此次B發(fā)送的數(shù)據(jù)從序號10391980開始,共2800個數(shù)據(jù)。
[8199]A->B ?Seq = 10147 ?Ack = 10394780 ?Len = 0 ??沒有傳輸數(shù)據(jù),希望下一個收到的報文段的序號為10394780(10391980+2800)。
[8200]B->A ?Seq = 10394780 ?Ack = 10147 ?Len = 1400 ??因為[8199]沒有數(shù)據(jù),所以B希望收到的序號還是10147。此次B發(fā)送的數(shù)據(jù)從序號10394780開始,共1400個數(shù)據(jù)。
[8201]B->A ?Seq = 10396180 ?Ack = 10147 ?Len = 1400 ??此次B發(fā)送的數(shù)據(jù)從序號10396180開始,共1400個數(shù)據(jù)。
[8202]A->B ?Seq = 10147 ?Ack = 10397580 ?Len = 0 ??確認號10397580 = 10396180 + 1400表明[8201]之前的數(shù)據(jù)已經(jīng)正確接收了。
?
為什么TCP建立連接不是兩次握手也不是四次握手?
弄懂了TCP握手握的是什么后,再來分析握幾次。
四次握手的過程:
1.1 A 發(fā)送同步信號SYN + A's?Initial sequence number
1.2 B 確認收到A的同步信號,并記錄A's ISN 到本地,命名 B's ACK sequence number
1.3 B發(fā)送同步信號SYN + B's Initial sequence number?
1.4 A確認收到B的同步信號,并記錄B's ISN 到本地,命名 A's ACK sequence number并返回ACK。
很顯然1.2和1.3 這兩個步驟可以合并,只需要三次握手,可以提高連接的速度與效率。
?
如果A發(fā)給B的確認丟了,該如何?A會超時重傳這個ACK嗎?
答:A不會超時重傳,因為TCP不會為沒有數(shù)據(jù)的ACK超時重傳。處理方法是:B如果沒有收到A的ACK,會超時重傳自己的SYN同步信號,直到收到A的ACK為止。
?
二次握手的過程:
2.1 A 發(fā)送同步信號SYN + A's?Initial sequence number
2.2 B發(fā)送同步信號SYN + B's?Initial sequence number + B's ACK sequence number
這里有一個問題,A與B就A的初始序列號達成了一致,這里是1000。但是B無法知道A是否已經(jīng)接收到自己的同步信號,如果這個同步信號丟失了,A和B就B的初始序列號將無法達成一致。
于是TCP的設(shè)計者將SYN這個同步標志位SYN設(shè)計成占用一個字節(jié)的編號(FIN標志位也是),既然是一個字節(jié)的數(shù)據(jù),按照TCP對有數(shù)據(jù)的TCP segment 必須確認的原則,所以在這里A必須給B一個確認,以確認A已經(jīng)接收到B的同步信號。
?
補充閱讀
三次握手中的第三個包丟失,即A發(fā)給B的ACK中途被丟,沒有到達B,會有什么情況?
A發(fā)完ACK,單方面認為TCP為 Established狀態(tài),而B顯然認為TCP為Active狀態(tài):
a. 假定此時雙方都沒有數(shù)據(jù)發(fā)送,B會周期性超時重傳,直到收到A的確認,收到之后B的TCP 連接也為 Established狀態(tài),雙向可以發(fā)包。
b. 假定此時A有數(shù)據(jù)發(fā)送,B收到A的 Data + ACK,自然會切換為established 狀態(tài),并接受A的Data。
c. 假定B有數(shù)據(jù)發(fā)送,數(shù)據(jù)發(fā)送不了,會一直周期性超時重傳SYN + ACK,直到收到A的確認才可以發(fā)送數(shù)據(jù)。
總結(jié)
以上是生活随笔為你收集整理的TCP三次握手,握的是啥?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Raft 论文翻译
- 下一篇: 红黑树(RB-Tree)比AVL强在哪?