從本節(jié)開始茧痕,我們開始學(xué)習(xí)最重要的傳輸層归园。傳輸層位于OSI七層模型的第四層(從下往上)产艾。顧名思義医男,傳輸層的作用是實現(xiàn)應(yīng)用程序間的通信冰垄。網(wǎng)絡(luò)層的作用是保證數(shù)據(jù)在不同數(shù)據(jù)鏈路上傳輸?shù)目蛇_(dá)性蹬癌,至于如何傳輸則是由傳輸層負(fù)責(zé)。
一虹茶、傳輸層協(xié)議簡介
常見的傳輸層協(xié)議主要有TCP和UDP協(xié)議逝薪。
- TCP,TCP是面向有連接的協(xié)議蝴罪,也就是說在使用TCP協(xié)議傳輸數(shù)據(jù)之前董济,一定要在發(fā)送發(fā)和接收方建立連接。一般情況下建立連接需要三步要门,關(guān)閉連接需要四步虏肾。
建立TCP連接后,由于有數(shù)據(jù)重傳欢搜,流量控制等功能封豪,TCP能夠正確處理丟包問題,保證接收方能夠收到數(shù)據(jù)炒瘟,與此同時還能有效利用帶寬吹埠。然而TCP中定義了很多復(fù)雜的規(guī)范,因此效率不如UDP,所以不適合實時的視頻藻雌、音頻傳輸雌续。 - UDP
- 無連接,UDP是面向無連接的協(xié)議胯杭。不需要建立連接驯杜。
- 盡最大努力交付,它只會把數(shù)據(jù)發(fā)送給接收端做个,但是不關(guān)心接收端是否收到數(shù)據(jù)鸽心。但是這種特性反而適合多播,實時的視頻和音頻傳輸居暖,因為個別數(shù)據(jù)包的丟失并不會影響視頻和音頻的整體效果顽频。
- 面向報文,對應(yīng)用層的數(shù)據(jù)既不合并太闺,也不拆分糯景,而是直接在應(yīng)用層數(shù)據(jù)基礎(chǔ)上直接拼接udp首部,傳給網(wǎng)絡(luò)層(ip所在層)省骂。
- 關(guān)鍵要素
IP協(xié)議中的兩大關(guān)鍵要素是源IP地址和目標(biāo)IP地址蟀淮。而傳輸層我們剛剛說過,作用是實現(xiàn)應(yīng)用程序間的通信钞澳。因此傳輸層的協(xié)議中新增三個要素:源端口號怠惶、目標(biāo)端口號和協(xié)議號。通過這五個要素可以唯一識別一個通信轧粟。
不同的端口號策治,用于區(qū)分同一主機上的不同應(yīng)用程序。
協(xié)議號用于區(qū)分使用的是TCP還是UDP兰吟。
用一句話概括通惫,“源IP地址、目標(biāo)IP地址揽祥、源端口號讽膏、目標(biāo)端口號、協(xié)議號”這五個信息只要有一個不同拄丰,就被認(rèn)為是不同的通信。
二俐末、UDP首部
UDP協(xié)議最大的特點就是簡單料按,UDP首部如圖:
- 包長度,表示UDP首部和UDP數(shù)據(jù)長度之和卓箫。
-
檢驗和用于判斷數(shù)據(jù)在傳輸過程中是否有損壞载矿。計算這個校驗和的時候,不僅要考慮源端口號、目標(biāo)端口號闷盔,還要考慮IP首部中的源IP地址弯洗、目標(biāo)IP地址、協(xié)議號(這些又稱為UDP偽首部)逢勾。這是因為以上五個要素是識別通信時缺一不可牡整,如果校驗和只考慮端口號,那么另外三個要素在受到破壞時溺拱,應(yīng)用就無法得知逃贝。這可能導(dǎo)致不該收到包的應(yīng)用收到了包,該收到包的應(yīng)用沒有收到迫摔。
這個概念同樣適合于下面的TCP首部沐扳。
三、TCP首部
和UDP首部相比句占,TCP首部要復(fù)雜的多沪摄。解析這個首部的時間也會相應(yīng)的增加,這也是TCP連接的效率低于UDP的原因之一纱烘。
- 序列號卓起,它表示發(fā)送數(shù)據(jù)的位置,假設(shè)當(dāng)前的序列號為s凹炸,發(fā)送的數(shù)據(jù)長度為l戏阅,則下次發(fā)送數(shù)據(jù)時的序列號為s+l。在建立連接時啤它,通常由計算機隨機生成個數(shù)作為序列號的初始值奕筐。
- 確認(rèn)應(yīng)答號,它等于下一次應(yīng)該收到的數(shù)據(jù)的序列號变骡。比如發(fā)送端的序列號為s离赫,數(shù)據(jù)長度為l,則接收端返回的確認(rèn)應(yīng)答號也應(yīng)為s+l塌碌。發(fā)送端接收到這個確認(rèn)應(yīng)答后渊胸,可以認(rèn)為這個位置以前的所有數(shù)據(jù)已經(jīng)被正常接收。
- 數(shù)據(jù)偏移台妆,TCP首部的長度翎猛,單位為4字節(jié)。如果沒有可選字段接剩,那么這個值就是5切厘,表示TCP首部的長度為20字節(jié)。
- 控制位懊缺,該字段有8比特疫稿,分別有8個控制標(biāo)志。依次是 CWR,ECE遗座,URG舀凛,ACK,PSH途蒋,RST猛遍,SYN 和 FIN。在后續(xù)的文章中會接觸到其中的幾個碎绎。
- 窗口大小螃壤,用于表示從應(yīng)答號開始能夠接受多少個8位字節(jié)。如果窗口大小為0筋帖,可以發(fā)送窗口探測奸晴。
- 緊急指針,僅在URG控制位是1時有效日麸。表示緊急數(shù)據(jù)的末尾在TCP數(shù)據(jù)部分中的位置寄啼。通常在暫時中斷通信時使用。
四代箭、TCP握手
TCP是面向有連接的協(xié)議墩划,連接在每次通信前被建立,通信結(jié)束后被關(guān)閉嗡综。了解連接建立和關(guān)閉的過程通常是考察的重點乙帮。連接的建立和關(guān)閉可以用一張圖來表示:
通常情況下我們認(rèn)為客戶端首先發(fā)起連接請求。
1. 三次握手
1.發(fā)送端發(fā)送一個SYN=1极景,ACK=0標(biāo)志的數(shù)據(jù)包給接收端察净,請求進(jìn)行連接,這是第一次握手盼樟;
2.接收端收到請求并且允許連接的話氢卡,就會發(fā)送一個SYN=1,ACK=1標(biāo)志的數(shù)據(jù)包給發(fā)送端晨缴,告訴它译秦,可以通訊了,并且讓發(fā)送端發(fā)送一個確認(rèn)數(shù)據(jù)包击碗,這是第二次握手筑悴;
3.最后,發(fā)送端發(fā)送一個SYN=0延都,ACK=1的數(shù)據(jù)包給接收端雷猪,告訴它連接已被確認(rèn),這就是第三次握手晰房。之后,一個TCP連接建立,開始通訊殊者。
*SYN:同步標(biāo)志
同步序列編號(Synchronize Sequence Numbers)欄有效与境。該標(biāo)志僅在三次握手建立TCP連接時有效。它提示TCP連接的服務(wù)端檢查序列編號猖吴,該序列編號為TCP連接初始端(一般是客戶端)的初始序列編號摔刁。在這里,可以把TCP序列編號看作是一個范圍從0到4海蔽,294共屈,967,295的32位計數(shù)器党窜。通過TCP連接交換的數(shù)據(jù)中每一個字節(jié)都經(jīng)過序列編號拗引。在TCP報頭中的序列編號欄包括了TCP分段中第一個字節(jié)的序列編號。
*ACK:確認(rèn)標(biāo)志
確認(rèn)編號(Acknowledgement Number)欄有效幌衣。大多數(shù)情況下該標(biāo)志位是置位的矾削。TCP報頭內(nèi)的確認(rèn)編號欄內(nèi)包含的確認(rèn)編號(w+1,F(xiàn)igure-1)為下一個預(yù)期的序列編號豁护,同時提示遠(yuǎn)端系統(tǒng)已經(jīng)成功接收所有數(shù)據(jù)哼凯。
*RST:復(fù)位標(biāo)志
復(fù)位標(biāo)志有效。用于復(fù)位相應(yīng)的TCP連接楚里。
*URG:緊急標(biāo)志
緊急(The urgent pointer) 標(biāo)志有效断部。緊急標(biāo)志置位,
*PSH:推標(biāo)志
該標(biāo)志置位時班缎,接收端不將該數(shù)據(jù)進(jìn)行隊列處理蝴光,而是盡可能快將數(shù)據(jù)轉(zhuǎn)由應(yīng)用處理。在處理 telnet 或 rlogin 等交互模式的連接時吝梅,該標(biāo)志總是置位的虱疏。
*FIN:結(jié)束標(biāo)志
帶有該標(biāo)志置位的數(shù)據(jù)包用來結(jié)束一個TCP回話,但對應(yīng)端口仍處于開放狀態(tài)苏携,準(zhǔn)備接收后續(xù)數(shù)據(jù)
2.為什么是三次握手
根據(jù)一般思路做瞪,我們認(rèn)為第三次是多余的,TCP協(xié)議為什么還要增加第三次的握手呢右冻?
這是因為在網(wǎng)絡(luò)請求的時候装蓬,我們應(yīng)該時刻記住“網(wǎng)絡(luò)是不安全的,數(shù)據(jù)包是可能丟失的”纱扭。假設(shè)沒有第三次確認(rèn)牍帚,客戶端向服務(wù)端發(fā)送了SYN包,請求建立連接乳蛾。由于網(wǎng)絡(luò)原因暗赶,服務(wù)器沒有及時收到這個包鄙币,于是客戶端重新發(fā)送了SYN包。正常建立了連接蹂随。此時超時的那個確認(rèn)包到達(dá)了服務(wù)端十嘿,如果是兩次握手此連接就建立了,服務(wù)端就建立了一個空連接岳锁,白白浪費資源绩衷。如果是三次,客戶端判斷這個確認(rèn)包是無效的激率,就丟棄了咳燕。
3. 第三次握手的ACK包丟失
三次握手實際其實解決了第二步丟包問題。那么第三步的ACK包丟失了乒躺,TCP協(xié)議是如何處理的呢招盲?
按照TCP協(xié)議處理丟包問題的一般方法,服務(wù)器會重新向客戶端發(fā)送確認(rèn)包聪蘸,知道ACK確認(rèn)為止宪肖。但實際上這種做法有可能遭到SYN泛洪攻擊。所謂的泛洪攻擊健爬,是指發(fā)送方偽造多個IP地址控乾,模擬三次握手的過程。當(dāng)服務(wù)器返回ACK后娜遵,攻擊方故意不確認(rèn)蜕衡,從而使服務(wù)器不斷重發(fā)ACK。由于服務(wù)器長時間處于半連接狀態(tài)设拟,最后消耗過多的CUP和內(nèi)存資源導(dǎo)致死機慨仿。
所以服務(wù)端采用的是這種方法,發(fā)送RST數(shù)據(jù)包纳胧,進(jìn)入close狀態(tài)镰吆,這個RST數(shù)據(jù)包中的TCP首部中的控制位中的RST位被置為1。這表示連接信息全部被初始化跑慕,原有的TCP通信不能繼續(xù)万皿。客戶端如果還想建立TCP連接核行,需要從第一步握手重新開始牢硅。
五、四次揮手關(guān)閉連接
(1)客戶端A發(fā)送一個FIN芝雪,用來關(guān)閉客戶A到服務(wù)器B的數(shù)據(jù)傳送(報文段4)减余。
(2)服務(wù)器B收到這個FIN,它發(fā)回一個ACK惩系,確認(rèn)序號為收到的序號加1(報文段5)位岔。和SYN一樣如筛,一個FIN將占用一個序號。
(3)服務(wù)器B關(guān)閉與客戶端A的連接赃承,發(fā)送一個FIN給客戶端A(報文段6)妙黍。
(4)客戶端A發(fā)回ACK報文確認(rèn)悴侵,并將確認(rèn)序號設(shè)置為收到序號加1(報文段7)瞧剖。
- 關(guān)閉連接的最后一個 ACK 丟失怎么辦?
實際上,在第三步中可免,客戶端收到 FIN 包時抓于,它會設(shè)置一個計時器,等待相當(dāng)長的一段時間浇借。如果客戶端返回的 ACK 丟失捉撮,那么服務(wù)端還會重發(fā) FIN 并重置計時器。假設(shè)在計時器失效前服務(wù)器重發(fā)的 FIN 包沒有到達(dá)客戶端妇垢,客戶端就會進(jìn)入 CLOSE 狀態(tài)巾遭,從而導(dǎo)致服務(wù)端永遠(yuǎn)無法收到 ACK 確認(rèn),也就無法關(guān)閉連接闯估。 - 為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報文段生存時間)才能返回到CLOSE狀態(tài)灼舍?
這樣能夠保證第四次揮手不管在正常情況下還是丟包情況下都不會出現(xiàn)問題。
正常情況下涨薪,客戶端A把第四次揮手的ACK報文發(fā)送給客戶端B骑素,這個報文在一個MSL內(nèi)能夠成功到達(dá)。盡管A會多等一個MSL的時間也不會有什么問題刚夺。
如果出現(xiàn)第四次丟包的情況献丑,也就是A發(fā)送ACK包給B以后,正常情況下在一個MSL的時間內(nèi)B是肯定能收到的侠姑,如果B沒有收到创橄,B會重新發(fā)送FIN包,這個重新發(fā)送的FIN包在MSL時間內(nèi)也是能夠到達(dá)的莽红。
所以2MLS時間之后妥畏,就確保了當(dāng)前連接上沒有任何報文了,可以正常關(guān)閉了船老。