?????? 我們知道TCP協(xié)議是一種面向連接,通過“三次握手”機(jī)制而建立的可靠的傳輸協(xié)議。下面來了解一下“三次握手”機(jī)制是如何實(shí)現(xiàn)可靠的:
?????? 現(xiàn)實(shí)錯(cuò)綜復(fù)雜的網(wǎng)絡(luò),讓每一次請(qǐng)求響應(yīng)都充滿了不確定性,而“三次握手”機(jī)制也是從請(qǐng)求和響應(yīng)來實(shí)現(xiàn)它的目標(biāo)的。假設(shè)網(wǎng)絡(luò)正常,我們來看看“三次握手”機(jī)制的執(zhí)行流程:

SYN 是英文同步synchronize的縮寫;ACK是英文acknowledgement的縮寫。
?????? 從上圖可以體會(huì)的到,請(qǐng)求的發(fā)起方先發(fā)送一個(gè)編號(hào)為0的SYN包到接收方,接收方接收到這個(gè)SYN包之后,首先肯定是要通知發(fā)送方我已經(jīng)接受到了你的SYN請(qǐng)求,也就是我們上面說的ACK。但同時(shí)按照上面描述的,如果想建立連接,就必須發(fā)送SYN,所以,對(duì)于接收方,就有兩個(gè)需要發(fā)送的包,亦或是說兩個(gè)被置不同標(biāo)識(shí)的包,但是很明顯,這兩個(gè)包是可以合并的,所以說,發(fā)送方就會(huì)發(fā)送一個(gè)TCP包,這個(gè)包里,SYN位和ACK位同時(shí)被置上?;氐桨l(fā)送方,在接收到這個(gè)對(duì)端發(fā)送來的SYN包之后,同樣要回一個(gè)ACK包給對(duì)端。此時(shí),TCP連接就建立好了,后面的通信中,兩端就可以自由的發(fā)送數(shù)據(jù)和消息了
?????? 然而,現(xiàn)實(shí)網(wǎng)絡(luò)往往不如所愿,三次握手過程中每次發(fā)的消息,都有可能出現(xiàn)丟失、延遲到達(dá)、重復(fù)這三種情況,任何一種情況都可能會(huì)讓建立連接失敗。那么,“三次握手”機(jī)制是如何實(shí)現(xiàn)可靠建立的呢?
?????? 在TCP中,發(fā)送消息的時(shí)候會(huì)啟動(dòng)一個(gè)計(jì)時(shí)器,這個(gè)計(jì)時(shí)器在收到相應(yīng)回復(fù)的時(shí)候會(huì)重置而重新計(jì)時(shí),而如果一直沒有收到相應(yīng)的回復(fù),在計(jì)時(shí)器到期的時(shí)候發(fā)送端就會(huì)重發(fā)消息,這是TCP重傳機(jī)制里面第一層的保障。
因?yàn)門CP發(fā)起連接的時(shí)候只有三條消息,所以丟失也就三種情況:
第一個(gè)SYN消息丟失,即發(fā)起者的發(fā)起請(qǐng)求丟失了,所以接收者也就不會(huì)回送SYN-ACK消息,因?yàn)樗麤]有得消息刺激他回應(yīng)。所以過一段時(shí)間后發(fā)起者發(fā)現(xiàn)自己沒有收到回應(yīng)消息,于是在計(jì)時(shí)器到期后,發(fā)起端會(huì)重發(fā)SYN消息。如果在經(jīng)過了幾次重傳仍然沒有成功以后,嘗試連接過程就終止了。
第二個(gè)SYN-ACK消息丟失,發(fā)送端本質(zhì)上和上一種情況相同。接收者因?yàn)榇_實(shí)已經(jīng)收到了SYN消息并發(fā)送了回復(fù)消息,所以其計(jì)時(shí)器已經(jīng)啟動(dòng)了。在計(jì)時(shí)器到期之后,接收端會(huì)重發(fā)SYN-ACK消息,如果幾次之后還沒有成功,那么接收端會(huì)發(fā)送RST終止連接。
第三個(gè)來自發(fā)送端的ACK丟失,接收端本質(zhì)上會(huì)上一種情況相同,最終會(huì)發(fā)送RST消息終止連接。
在linux的TCP-IP協(xié)議的實(shí)現(xiàn)中,分別使用兩個(gè)不同的計(jì)時(shí)器,在發(fā)送端啟動(dòng)是普通的超時(shí)計(jì)時(shí)器,在接收端啟動(dòng)的是SYN-ACK計(jì)時(shí)器。超時(shí)計(jì)時(shí)器就是在發(fā)送端發(fā)送SYN的時(shí)候開始計(jì)時(shí),默認(rèn)是1秒,如果過了1秒沒有收到確認(rèn),會(huì)再次發(fā)送SYN,然后將計(jì)時(shí)器設(shè)置成為2秒,然后依4秒,8秒,16秒,以此類推。當(dāng)然,在代碼中有一個(gè)重試上限,在linux上的默認(rèn)是設(shè)置為5次。同樣的SYN-ACK計(jì)時(shí)器在接收端接收到SYN之后發(fā)出SYN-ACK消息之后啟動(dòng),間隔和重試次數(shù)和普通計(jì)時(shí)器都是一致的,當(dāng)然他會(huì)做一些其他的事情所以和普通計(jì)時(shí)器是有一些區(qū)別的。
我們考慮實(shí)際中的情況二,發(fā)送端發(fā)送SYN后未收到SYN-ACK消息,同時(shí)啟動(dòng)計(jì)時(shí)器A,過了一小段時(shí)間之后,接收端接收到了SYN消息,啟動(dòng)計(jì)時(shí)器B,發(fā)送SYN-ACK消息,但是這個(gè)消息丟失了。1秒鐘后,發(fā)送端由于A到期,重發(fā)SYN,而幾乎與此同時(shí)接收端也會(huì)由于B到期重發(fā)SYN-ACK消息。那么問題來了,假設(shè)這個(gè)時(shí)候重發(fā)的SYN又一次成功的到達(dá)了接收端會(huì)怎樣?答案很簡(jiǎn)單,接收端會(huì)忽略它,因?yàn)閟eq序號(hào)重復(fù)了。接收端既不會(huì)再一次發(fā)送SYN-ACK消息,也不會(huì)重置計(jì)時(shí)器。于是就避免不斷重復(fù)的重發(fā),造成網(wǎng)絡(luò)混亂甚至崩潰。
如果用一句話總結(jié)的話,就是通過超時(shí)計(jì)時(shí)器和序號(hào)的重復(fù)檢測(cè)
?????? 計(jì)時(shí)器和序號(hào)機(jī)制,計(jì)時(shí)器是解決響應(yīng)超時(shí)重新發(fā)包(重傳機(jī)制),序號(hào)機(jī)制是指再次發(fā)出的數(shù)據(jù)包標(biāo)記序號(hào)和上一次的數(shù)據(jù)包是一樣的。同樣的序號(hào)的數(shù)據(jù)包被接收方接收到后,可以忽略不做任何響應(yīng)。這兩個(gè)機(jī)制避免不斷重發(fā),造成網(wǎng)絡(luò)混亂甚至崩潰。