官术网_书友最值得收藏!

1.1 網絡傳輸協議

1.1.1 UDP

UDP為應用程序提供了一種以最少的協議機制將消息發送到目的應用程序的方法,RFC(Request for Comments,請求意見稿)768對它進行了定義。UDP提供了應用程序間根據端口號復用和解復用的方法,以及可選校驗,是非常輕量級的協議。UDP首部格式如圖1-1所示。

使用UDP的應用程序的數據可以直接在數據報內發送,不需要建立連接,也對可靠性和順序保證沒有要求。UDP效率高、速度快、消耗低、延遲小,適合于實時性要求較高的場景,如視頻會議、網絡游戲。

由于TCP和UDP出現較早,使用非常廣泛,很多中間件和內核都能很好地支持它們,因此互聯網協議大多會選擇它們。如果不需要TCP提供的全套功能,需要定制傳輸行為的協議也會選擇基于UDP實現。

圖1-1 UDP首部格式

1.1.2 TCP

TCP起源于20世紀60年代末的一個分組交換網絡研究項目,現在已成為全球互聯網的基礎。TCP是一種面向連接的傳輸層通信協議,兩個端點通過三次握手建立連接后就可以按照順序收發數據。TCP的實現包括可靠、保序、去重、流控、擁塞控制等功能。

TCP首部格式如圖1-2所示。TCP使用四元組(源IP、源端口號、目的IP、目的端口號)來確定一個連接。序號用來確定字節流的位置,應用程序發送的字節流是從0開始的,但序號從一個隨機值開始,這主要是為了防止猜測攻擊和新舊連接間的沖突。確認號是為了讓發送方知道哪些數據被接收到了,哪些需要重傳。

圖1-2 TCP首部格式

TCP通過三次握手建立連接,如圖1-3所示;通過四次揮手關閉連接,如圖1-4所示。

圖1-3 TCP的三次握手

TCP的細節內容比較多,這里就不詳盡地描述了。下面主要介紹幾個對參考QUIC(Quick UDP Internet Connections,快速UDP連接)實現比較重要的內容,以及TCP的應對措施。

1.TCP確認

TCP的標準確認機制是累積確認,如果數據亂序到達,接收端只會重復確認最后一個按序到達的報文。TCP應用數據的發送和確認原理如圖1-5所示。圖1-5中,假設起始序號為100(但實際上隨機值一般是個很大的值),第一個包含數據的TCP報文序號是100,長度是5,對應了應用數據0~4字節的絕對偏移,對端確認這個報文中確認號是105,表示105之前的數據都已經收到了,希望下一個報文的序號從105開始(相對于應用數據的絕對偏移量5),這個確認報文中的序號是對端確定的隨機值X。第二個包含數據的TCP報文序號從105開始,長度為5,對應了應用數據5~9字節的絕對偏移,對端收到后回復序號X(因為對端沒有發送任何應用數據,所以序號不變),確認號110,表示希望下一次發送序號為110的報文。

圖1-4 TCP四次揮手

從上文可以看出,TCP的累積確認可能會導致在亂序的情況下重傳已經收到的數據,如圖1-6所示。

圖1-6中,應用數據3~5字節的絕對偏移對應的TCP報文丟失(對應序號103),后面再發送應用數據的6~8字節,回復也只會是確認號103。只能先重傳序號103字節的TCP報文,再重傳序號106的TCP報文,但實際上序號106的TCP報文之前已經到達了對端。

為了解決這個問題,TCP提供了一種確認的優化方案SACK(Selective Acknowledgement),即選擇性確認,可以不按照順序確認報文。SACK是一個可選機制,需要發送端和接收端協商,SACK選項格式如圖1-7所示。

圖1-5 TCP應用數據的發送和確認原理

圖1-6 TCP丟包情況下的確認

圖1-7 SACK選項格式

在TCP實現的默認方式中,只有TCP首部中的ACK字段可用,所以確認時只能傳遞一個數值——期望序號。如果想要傳遞更多的確認信息,則是需要擴展TCP選項SACK來實現,SACK選擇可以攜帶幾個分散的確認塊。由于整個TCP選項的長度不能超過40字節,所以攜帶的確認塊數不能超過4個(SACK選項中類型占1字節,長度占1字節,每個邊界占4字節)。這在一定程度上加快了TCP的發送速度,減少了虛假重傳。

2.TFO

在傳統的TCP實現中,必須經過三次握手才能夠發送數據,為了盡快發送數據,人們提出了TCP Fast Open(TCP快速打開),即TFO,RFC 7413對它進行了定義。TFO是一種TCP重新連接時快速發出數據的方法,具體過程如下。

1)首次建立TCP連接時,客戶端在發送SYN的同時攜帶了Fast Open(快速打開)選項,其中Cookie為空,這表明客戶端請求服務器提供Cookie;服務器將Cookie發送給客戶端。

2)重新連接時,客戶端在發送SYN的同時在Fast Open選項中攜帶了之前服務器提供的Cookie數據;服務器驗證Cookie通過后,接收攜帶的數據。

TFO的使用方法如圖1-8所示,雖然TFO可以將數據發送提前,但是需要客戶端、服務器和中間件都支持這樣做??蛻舳说腡CP實現一般在操作系統中,難以獨自升級;中間件可能不受客戶和服務提供者的控制;再加上存在的安全問題,所以很難快速廣泛應用。

3.MPTCP

改變本地IP地址會導致TCP重新建立連接,而當今移動終端越來越多,需要能夠在網絡之間無縫切換。解決這個問題的方案是利用MPTCP(MultiPath TCP,多路TCP),標準見RFC 6824。另外,MPTCP也被用于利用多個信道增加傳輸速率。

1.1.3 SCTP

既然已經有了可靠傳輸的TCP和不可靠傳輸的UDP,我們的場景不就全覆蓋了嗎?為什么還需要新的傳輸協議呢?下面從SCTP(Sream Control Transmission Protocol,流控制傳輸協議)的產生和發展的歷史來說明。

從20世紀80年代起,隨著IP技術的飛速發展,IP網絡變得越來越普及。電話網絡跟IP網絡仍然是兩個網絡,且電話網絡單獨組建的成本較高。通過IP網絡傳輸電話信號更加經濟,因此可借助IP網絡的多路徑實現更可靠傳輸。為了使IP網絡的普遍性可達范圍更廣,需要選擇一種傳輸協議實現這種需求。

圖1-8 TFO的使用方法

當時普遍使用的傳輸協議是TCP和UDP,如果選擇TCP,有如下問題。

●多個用戶的電話在TCP中排隊傳輸,可能所有用戶都要等待一個用戶的重傳。

●TCP是基于字節流的,需要使用者實現消息的拆分,也很難做到將過期數據丟棄。

●電話需要高可靠性,TCP不能支持多路徑。

●TCP沒有內置安全性和認證,容易受到SYN Flood攻擊。

如果選擇UDP,使用者則需要先實現以下功能。

●消息排序和消除重復內容。

●檢測丟包和重傳。

●擁塞控制。通過擁塞控制可以更好地利用網絡帶寬,提高帶寬利用率,從而避免大量報文阻塞網絡,提高傳輸效率,還與其他應用公平分享帶寬,避免互相影響。

●PMTU(Path Maximum Transmission Unit,路徑最大傳輸單元)探測。不探測PMTU就難以在保證可靠性的條件下提高網絡承載比,甚至可靠性都難以實現。

●流量控制。通過流量控制可避免接收端因緩存滿了而無法接收的情況下,發送端還在發送消息,白白消耗資源。

可見TCP和UDP都不適用于電話信號傳輸。于是在1997年,產生了新的傳輸協議MDTP(Multi-Network Datagram Transmission Protocol,多網數據報傳輸協議),并于1998年提交給了IETF(The Internet Engineering Task Force,因特網工程任務組)。這促成了SIGTRAN(Signaling Transport,信號傳輸)工作組的成立,其目標是廢除現存電話信號協議,包括ISUP(ISDN User Part,ISDN用戶部分)、DSS1(Digital Subscriber Siganaling No.1,1號數字用戶信令)等,生成電話信號在純IP網絡中傳輸的協議。經過1998~2000年集中討論后MDTP改名為SCTP,2000年標準化為RFC 2960,并移交給TSVWG(Transport Area Working Group,傳輸領域工作組)。之后又更新為RFC 4960,并于2022年最終更新為RFC 9260。

SCTP最初的目的是為了保證七號信令在無QoS(Quality of Service,服務質量)保證的IP網絡上完全可靠傳輸,語音流則可以半可靠傳輸,這也就是SIGTRAN工作組的目標。雖然之后轉交給了TSVWG,希望走向更通用的傳輸協議方向,但電話信號傳輸的出身仍然影響了其適用場景。

SCTP作為一種類似TCP的傳輸協議,可以按序可靠傳輸數據并同樣有擁塞控制功能,且與UDP一樣以消息為粒度發送和交付。SCTP支持應用數據的可靠不按序傳輸、不可靠傳輸通過部分可靠功能中設置重傳次數限制實現。和基于時間的部分可靠傳輸。SCTP還可以支持多宿主和多流,多宿主指的是端點可以在一個偶聯中使用多個地址,多流可以將應用數據分開傳輸,避免隊頭阻塞。具體來說SCTP有以下特征。

1)基于消息(不同于TCP基于字節流)的順序傳輸,可以將應用程序要發送的小塊數據組成PMTU范圍內的大數據包,把應用程序要發送的大塊數據拆分成適合PMTU的相對較小數據包,并在接收端重新組裝后發給上層應用。對于基于消息的上層應用來說,這樣就不需要自己定義結構去維護消息邊界了。

2)多流中的每個流分別可靠地按序傳送消息,一個流的數據丟失不會影響其他流的進度,從而解決了TCP的隊頭阻塞問題。

3)多宿主中的每個端點都可以有多個IP地址,可以接入多個網絡。當一個網絡出現了問題,SCTP立即切換到其他網絡,再利用路徑的冗余實現端到端的可靠性和路徑間的負載分擔,這樣就充分利用了網絡帶寬。

4)基于Cookie的四次握手(見圖1-9)針對TCP的三次握手的SYN Flood攻擊做出了改進。

圖1-9 SCTP四次握手

5)三次揮手機制(見圖1-10)可避免TCP的半關閉狀態問題。SCTP采用了認證機制,每一個消息都包含了歸屬SCTP偶聯的認證標記,所以不會出現像TCP一樣新舊連接的混淆問題,所以也就不需要TIME_WAIT狀態。

6)首部中包含了兩端協商的驗證標簽,如果收到的SCTP報文驗證標簽錯誤就丟棄,具有更高的安全性。

7)SACK確認方式可以將接收到的不連續的控制塊告知發送端,發送端根據這些接收信息重新發送接收方沒有收到的數據。不用像經典TCP一樣,需要等待沒有收到的數據塊,才能繼續確認后面的數據。這樣可以提高發送方的傳輸效率,避免接收到的不連續數據塊的重傳,也可以更積極地發現丟失的報文,以便盡快重傳。TCP雖然后來也出現了SACK功能,但是將其作為可選項,需要兩端協商。SCTP則將SACK作為唯一的確認方式。

圖1-10 SCTP三次揮手

SCTP最初是被設計為在IP網路上傳輸公共交換電話網絡(Public Switched Telephone Network,PSTN)消息。目前,SCTP已經被用于4G通信中eNB(Evolved Node B,演進型基站)和eNB的通信,5G通信中gNB(the next Generation Node B,下一代基站)和AMF(Authentication Management Function,認證管理功能)、gNB和gNB的通信。SCTP的主要應用場景還是在運營商內部,終端的應用目前還很少使用,原因如下。

●操作系統支持有限,很多操作系統是不支持SCTP的。實際上最終Linux支持的也不是原生的SCTP,而是基于UDP的SCTP。

●中間設備支持有限,比如NAT(Network Address Translation,網絡地址轉換)、防火墻等可能會丟棄SCTP報文。

●協議復雜,不容易理解,相對于TCP來說使用也不方便,用戶不習慣(尤其是已經習慣了TCP)。

●調試不方便、工具少,不像TCP、UDP有很多工具可以用于調試和分析。

●上層應用協議沒有支持,比如HTTP等。

●SCTP源于運營商需求,很多特性都是針對運營商的內部場景定制的,未必契合終端用戶的需求。

但是我們也看到一些終端應用傳輸在嘗試使用SCTP。比如WebRTC(Web Real-Time Communications,網絡實時通信)支持SCTP傳輸,但是使用的是SCTP over UDP,使用UDP主要是為了解決內核和中間件的支持問題,但不支持多宿主,丟失了SCTP的部分可靠性。RFC 6951中詳細介紹了SCTP over UDP的實現。

有趣的是MDTP最初就是基于UDP的,IETF最終決定SCTP應該直接用于IP,否決了MDTP基于UDP的方案。但是直接基于IP意味著SCTP必須進入內核,這是個非常長久的過程,而且內核可能考慮到中間件的影響和應用的選擇,不太愿意接納原生的SCTP。Linux內核沒有選擇原生的SCTP,而是從5.11.0版本開始支持SCTP over UDP,可見終端上的傳輸層還是要適應多樣的終端操作系統和復雜的網絡中間件,無法完全拋開TCP和UDP。

1.1.4 其他協議

互聯網協議還有一些其他的傳輸協議,比如KCP、RTP(Real-time Transport Protocol,實時傳輸協議)等。

KCP也是一種保證可靠性的傳輸協議,雖然沒有規定下層傳輸方式,但一般使用UDP。TCP更看重帶寬利用率,盡量用有限的帶寬傳輸盡量多的數據;而KCP則犧牲了一部分帶寬,換取更快的傳輸,更合適于時延要求比較嚴格的應用。相對TCP來說,KCP采取了更積極的重傳,一般還會啟用前向糾錯,用更高的帶寬占用換取傳輸效率,多用于游戲加速等場景。

RTP經常與RTCP(Real-time Transport Control Protocol,實時傳輸控制協議)配合傳輸實時數據,比如交互式音頻和視頻數據。RTCP用于傳遞控制信息,RTP用于傳輸實時數據,具體實現參見RFC 3550。RTCP為RTP的傳輸質量提供反饋信息,RTP可以根據這些信息調整發送速率或者發送策略,另外RTCP為RTP提供了全局唯一的標識(CNAME)和用戶加入離開等控制信息。為了實現終端和中間件的兼容性,RTP和RTCP通常都是基于UDP傳輸的,一般用于交互式視頻和音頻傳輸,可用于組播場景,如圖1-11所示。

圖1-11 RTP和RTCP

主站蜘蛛池模板: 梓潼县| 丹凤县| 航空| 平山县| 河东区| 南陵县| 云浮市| 内江市| 武冈市| 中卫市| 萨迦县| 濮阳县| 郴州市| 公主岭市| 洪泽县| 江孜县| 福安市| 青铜峡市| 虞城县| 西安市| 平潭县| 清远市| 宾川县| 绥棱县| 娄烦县| 吐鲁番市| 肇东市| 溆浦县| 凤阳县| 吉水县| 鄱阳县| 临城县| 康保县| 苗栗县| 吴旗县| 十堰市| 富顺县| 西贡区| 长阳| 宁海县| 云和县|