TCP/IP(四):TCP 与 UDP 协议简介
從本章開始,我們開始介紹最重要的傳輸層。傳輸層位于 OSI 七層模型的第四層(由下往上)。顧名思義,傳輸層的主要作用是實(shí)現(xiàn)應(yīng)用程序之間的通信。網(wǎng)絡(luò)層主要是保證不同數(shù)據(jù)鏈路下數(shù)據(jù)的可達(dá)性,至于如何傳輸數(shù)據(jù)則是由傳輸層負(fù)責(zé)。
傳輸層協(xié)議簡(jiǎn)介
常見的傳輸層協(xié)議主要有 TCP 協(xié)議和 UDP 協(xié)議。TCP 協(xié)議是面向有連接的協(xié)議,也就是說(shuō)在使用 TCP 協(xié)議傳輸數(shù)據(jù)之前一定要在發(fā)送方和接收方之間建立連接。一般情況下建立連接需要三步,關(guān)閉連接需要四步。
建立 TCP 連接后,由于有數(shù)據(jù)重傳、流量控制等功能,TCP 協(xié)議能夠正確處理丟包問(wèn)題,保證接收方能夠收到數(shù)據(jù),與此同時(shí)還能夠有效利用網(wǎng)絡(luò)帶寬。然而 TCP 協(xié)議中定義了很多復(fù)雜的規(guī)范,因此效率不如 UDP 協(xié)議,不適合實(shí)時(shí)的視頻和音頻傳輸。
UDP 協(xié)議是面向無(wú)連接的協(xié)議,它只會(huì)把數(shù)據(jù)傳遞給接收端,但是不會(huì)關(guān)注接收端是否真的收到了數(shù)據(jù)。但是這種特性反而適合多播,實(shí)時(shí)的視頻和音頻傳輸。因?yàn)閭€(gè)別數(shù)據(jù)包的丟失并不會(huì)影響視頻和音頻的整體效果。
IP 協(xié)議中的兩大關(guān)鍵要素是源 IP 地址和目標(biāo) IP 地址。而剛剛我們說(shuō)過(guò),傳輸層的主要作用是實(shí)現(xiàn)應(yīng)用程序之間的通信。因此傳輸層的協(xié)議中新增了三個(gè)要素:源端口號(hào),目標(biāo)端口號(hào)和協(xié)議號(hào)。通過(guò)這五個(gè)信息,可以唯一識(shí)別一個(gè)通信。
不同的端口用于區(qū)分同一臺(tái)主機(jī)上不同的應(yīng)用程序。假設(shè)你打開了兩個(gè)瀏覽器,瀏覽器 A 發(fā)出的請(qǐng)求不會(huì)被瀏覽器 B 接收,這就是因?yàn)?A 和 B 具有不同的端口。
協(xié)議號(hào)用于區(qū)分使用的是 TCP 還是 UDP。因此相同兩臺(tái)主機(jī)上,相同的兩個(gè)進(jìn)程之間的通信,在分別使用 TCP 協(xié)議和 UDP 協(xié)議時(shí)也可以被正確的區(qū)分開來(lái)。
用一句話來(lái)概括就是:“源 IP 地址,目標(biāo) IP 地址,源端口號(hào),目標(biāo)端口號(hào)和協(xié)議號(hào)”這五個(gè)信息只要有一個(gè)不同,都被認(rèn)為是不同的通信。
UDP 首部
UDP 協(xié)議最大的特點(diǎn)就是簡(jiǎn)單,它的首部如下圖所示:
UPD 首部
包長(zhǎng)度表示 UDP 首部的長(zhǎng)度和 UPD 數(shù)據(jù)長(zhǎng)度之和。
校驗(yàn)和用來(lái)判斷數(shù)據(jù)在傳輸過(guò)程中是否損壞。計(jì)算這個(gè)校驗(yàn)和的時(shí)候,不僅考慮源端口號(hào)和目標(biāo)端口號(hào),還要考慮 IP 首部中的源 IP 地址,目標(biāo) IP 地址和協(xié)議號(hào)(這些又稱為 UDP 偽首部)。這是因?yàn)橐陨衔鍌€(gè)要素用于識(shí)別通信時(shí)缺一不可,如果校驗(yàn)和只考慮端口號(hào),那么另外三個(gè)要素收到破壞時(shí),應(yīng)用就無(wú)法得知。這有可能導(dǎo)致不該收到包的應(yīng)用收到了包,改收到包的應(yīng)用反而沒(méi)有收到。
這個(gè)概念同樣適用于即將介紹的 TCP 首部。
TCP 首部
和 UDP 首部相比,TCP 首部要復(fù)雜得多。解析這個(gè)首部的時(shí)間也相應(yīng)的會(huì)增加,這是導(dǎo)致 TCP 連接的效率低于 UDP 的原因之一。
TCP 首部
其中某些關(guān)鍵字段解釋如下:
-
序列號(hào):它表示發(fā)送數(shù)據(jù)的位置,假設(shè)當(dāng)前的序列號(hào)為 s,發(fā)送數(shù)據(jù)長(zhǎng)度為 l,則下次發(fā)送數(shù)據(jù)時(shí)的序列號(hào)為 s + l。在建立連接時(shí)通常由計(jì)算機(jī)生成一個(gè)隨機(jī)數(shù)作為序列號(hào)的初始值。
-
確認(rèn)應(yīng)答號(hào):它等于下一次應(yīng)該接收到的數(shù)據(jù)的序列號(hào)。假設(shè)發(fā)送端的序列號(hào)為 s,發(fā)送數(shù)據(jù)的長(zhǎng)度為 l,那么接收端返回的確認(rèn)應(yīng)答號(hào)也是 s + l。發(fā)送端接收到這個(gè)確認(rèn)應(yīng)答后,可以認(rèn)為這個(gè)位置以前所有的數(shù)據(jù)都已被正常接收。
-
數(shù)據(jù)偏移:TCP 首部的長(zhǎng)度,單位為 4 字節(jié)。如果沒(méi)有可選字段,那么這里的值就是 5。表示 TCP 首部的長(zhǎng)度為 20 字節(jié)。
-
控制位:改字段長(zhǎng)度為 8 比特,分別有 8 個(gè)控制標(biāo)志。依次是 CWR,ECE,URG,ACK,PSH,RST,SYN 和 FIN。在后續(xù)的文章中你會(huì)陸續(xù)接觸到其中的某些控制位。
-
窗口大小:用于表示從應(yīng)答號(hào)開始能夠接受多少個(gè) 8 位字節(jié)。如果窗口大小為 0,可以發(fā)送窗口探測(cè)。
-
緊急指針:盡在 URG 控制位為 1 時(shí)有效。表示緊急數(shù)據(jù)的末尾在 TCP 數(shù)據(jù)部分中的位置。通常在暫時(shí)中斷通信時(shí)使用(比如輸入 Ctrl + C)。
TCP 握手
TCP 是面向有連接的協(xié)議,連接在每次通信前被建立,通信結(jié)束后被關(guān)閉。了解連接建立和關(guān)閉的過(guò)程通常是考察的重點(diǎn)。連接的建立和關(guān)閉過(guò)程可以用一張圖來(lái)表示:
TCP 連接建立和關(guān)閉
通常情況下,我們認(rèn)為客戶端首先發(fā)起連接。
三次握手建立連接
這個(gè)過(guò)程可以用以下三句形象的對(duì)話表示:
為什么是三次握手
根據(jù)一般的思路,我們可能會(huì)覺(jué)得只要兩次握手就可以了,第三步確認(rèn)看似是多余的。那么 TCP 協(xié)議為什么還要費(fèi)力不討好的加上這一次握手呢?
這是因?yàn)樵诰W(wǎng)絡(luò)請(qǐng)求中,我們應(yīng)該時(shí)刻記住:“網(wǎng)絡(luò)是不可靠的,數(shù)據(jù)包是可能丟失的”。假設(shè)沒(méi)有第三次確認(rèn),客戶端向服務(wù)端發(fā)送了 SYN,請(qǐng)求建立連接。由于延遲,服務(wù)端沒(méi)有及時(shí)收到這個(gè)包。于是客戶端重新發(fā)送一個(gè) SYN 包。回憶一下介紹 TCP 首部時(shí)提到的序列號(hào),這兩個(gè)包的序列號(hào)顯然是相同的。
假設(shè)服務(wù)端接收到了第二個(gè) SYN 包,建立了通信,一段時(shí)間后通信結(jié)束,連接被關(guān)閉。這時(shí)候最初被發(fā)送的 SYN 包剛剛抵達(dá)服務(wù)端,服務(wù)端又會(huì)發(fā)送一次 ACK 確認(rèn)。由于兩次握手就建立了連接,此時(shí)的服務(wù)端就會(huì)建立一個(gè)新的連接,然而客戶端覺(jué)得自己并沒(méi)有請(qǐng)求建立連接,所以就不會(huì)向服務(wù)端發(fā)送數(shù)據(jù)。從而導(dǎo)致服務(wù)端建立了一個(gè)空的連接,白白浪費(fèi)資源。
在三次握手的情況下,服務(wù)端直到收到客戶端的應(yīng)答后才會(huì)建立連接。因此在上述情況下,客戶端會(huì)接受到一個(gè)相同的 ACK 包,這時(shí)候它會(huì)拋棄這個(gè)數(shù)據(jù)包,不會(huì)和服務(wù)端進(jìn)行第三次握手,因此避免了服務(wù)端建立空的連接。
ACK 確認(rèn)包丟失怎么辦
三次握手其實(shí)解決了第二步的數(shù)據(jù)包丟失問(wèn)題。那么第三步的 ACK 確認(rèn)丟失后,TCP 協(xié)議是如何處理的呢?
按照 TCP 協(xié)議處理丟包的一般方法,服務(wù)端會(huì)重新向客戶端發(fā)送數(shù)據(jù)包,直至收到 ACK 確認(rèn)為止。但實(shí)際上這種做法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊,是指發(fā)送方偽造多個(gè) IP 地址,模擬三次握手的過(guò)程。當(dāng)服務(wù)器返回 ACK 后,攻擊方故意不確認(rèn),從而使得服務(wù)器不斷重發(fā) ACK。由于服務(wù)器長(zhǎng)時(shí)間處于半連接狀態(tài),最后消耗過(guò)多的 CPU 和內(nèi)存資源導(dǎo)致死機(jī)。
正確處理方法是服務(wù)端發(fā)送 RST 報(bào)文,進(jìn)入 CLOSE 狀態(tài)。這個(gè) RST 數(shù)據(jù)包的 TCP 首部中,控制位中的 RST 位被設(shè)置為 1。這表示連接信息全部被初始化,原有的 TCP 通信不能繼續(xù)進(jìn)行。客戶端如果還想重新建立 TCP 連接,就必須重新開始第一次握手。
四次握手關(guān)閉連接
這個(gè)過(guò)程可以用以下四句形象的對(duì)話表示:
由于連接是雙向的,所以雙方都要主動(dòng)關(guān)閉自己這一側(cè)的連接。
關(guān)閉連接的最后一個(gè) ACK 丟失怎么辦
實(shí)際上,在第三步中,客戶端收到 FIN 包時(shí),它會(huì)設(shè)置一個(gè)計(jì)時(shí)器,等待相當(dāng)長(zhǎng)的一段時(shí)間。如果客戶端返回的 ACK 丟失,那么服務(wù)端還會(huì)重發(fā) FIN 并重置計(jì)時(shí)器。假設(shè)在計(jì)時(shí)器失效前服務(wù)器重發(fā)的 FIN 包沒(méi)有到達(dá)客戶端,客戶端就會(huì)進(jìn)入 CLOSE 狀態(tài),從而導(dǎo)致服務(wù)端永遠(yuǎn)無(wú)法收到 ACK 確認(rèn),也就無(wú)法關(guān)閉連接。
示意圖如下:
TCP 關(guān)閉連接
文/bestswifter(簡(jiǎn)書作者)
原文鏈接:http://www.jianshu.com/p/dc456cf57e06
著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并標(biāo)注“簡(jiǎn)書作者”。
總結(jié)
以上是生活随笔為你收集整理的TCP/IP(四):TCP 与 UDP 协议简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TCP/IP(三):IP协议相关技术
- 下一篇: TCP/IP(五):TCP 协议详解