龍恒



摘? 要: 用戶數據報協議(UDP)是一種無連接傳輸層協議,提供的是一種不可靠的數據傳輸服務,不能保證將數據按順序、完整地傳送到目的地。本文引入了一些TCP的機制并進行了部分調整,在應用層上基于UDP實現了一個具有擁塞控制、重傳等機制的新的數據傳輸協議。測試結果表明使用該協議傳輸的所有數據都能正確地到達目的地,成功解決了可靠性問題,同時其他方面都能滿足設計要求。
關鍵詞: UDP; 可靠性; 重傳; 擁塞控制; 流量控制
中圖分類號:TP311? ? ? ? ? 文獻標識碼:A? ? ?文章編號:1006-8228(2020)04-33-05
A reliable transmission protocol based on UDP
Long Heng
(Maoming Polytechnic, Maoming, Guangdong 525000, China)
Abstract: User Datagram Protocol (UDP) is a connectionless transport layer protocol, it provides an unreliable data transmission service, and doesn't guarantee that the data transferred to the destination is in order and is integrated. This article introduces some TCP mechanisms and makes some improvement, to realize a UDP based new protocol with the mechanisms of congestion control and retransmission at the application layer. Test results show that all the data transmitted with the protocol can reach the destination correctly. It solved the reliability issues successfully and all aspects can meet the requirements.
Key words: UDP; reliability; retransmission; congestion control; flow control
0 引言
UDP是一種應用廣泛的傳輸層協議,但是傳輸過程中容易出現數據包的丟失或失序等問題。而TCP協議則供了一套完善的保證可靠性的機制,可以保證將數據按順序完整地發送到目的地。本文在UDP的基礎上,引入了一些TCP的概念,在應用層上實現了一個可靠的數據傳輸協議,稱為RUTP(Reliable Udp Transmission Protocol)。RUTP實現了接收方流量控制、擁塞控制、重傳和往返時間測量這些保證傳輸可靠性的基本機制[1],并且實現了SACK、Timestamp和Window Scale這三個對提高性能有幫助的功能。
1 協議首部
RUTP使用一個20字節的首部,結構如圖1所示,各個字段的含義如表1所示。
其中確認序號(acknowledgment)是一個32位的無符號整數。與RFC793中定義的acknowledgment number作用相同,是對接收到的字節數的確認,取值為被確認的數據包的序號(sequence)加上該數據包所攜帶的數據字節數,也就是下一個期望接收的字節的序號[2]。
另外還有一些只在特定數據包中才會出現的字段,稱為選項字段,其緊跟在RUTP固定首部字段之后。其中與保證可靠性有關的有兩個:SACK和PZW。SACK是選擇性確認字段,其功能與RFC2018中描述的相同[3],但是組織方式有所不同;PZW選項實現的是RFC1122的Probing Zero Windows[4]功能。在一個數據包中,RUTP首部出現在UDP首部之后。
2 系統變量
RUTP定義了一系列的系統變量,為了更好地講明問題,把本文中用到的變量做一個簡單的說明:
RMSS:接收方能接收的最大報文段。
SMSS:發送方能發送的最大報文段。
MAX_RECV_SEQ:接收到的數據包的最大序號。
MAX_RECV_ACK:接收到的數據包的最大確認序號。
LAST_SEND_SEQ:最后發送出去的序號,為最近一次發送出去的攜帶數據的數據包的序號加上其數據字節數。
LAST_SEND_ACK:最后發送出去的確認序號,為最近一次接收到的數據包的序號加上所包含的數據字節數。
TS_RECENT:記錄接收到的帶有數據的有效數據包的時間,當該數據包的序號小于等于LAST_
SEND_ACK的時候更新TS_RECENT的值。
FLIGHT_SIZE:當前發送出去但是還沒有被接收方確認的數據的字節數。
3 數據的接收
RUTP是一種全雙工協議,通訊的雙方可以同時接收和發送數據。其中接收流程如圖2所示。
3.1 滑動窗口
接收方使用一個稱為“滑動窗口”的機制進行流量控制,這是對接收方的接收緩沖區使用狀況的一個形象的描述,也是判斷數據包是否合法的重要依據之一,圖3顯示了一個滑動窗口在某個時間點的狀態。
用于描述滑動窗口的重要變量有:窗口大小的最大值(swMax),窗口左邊緣(swLeft)、當前窗口大小(swSize)、窗口的右邊緣(swRight),需要注意的是swLeft與swSize相加并不總是等于swRight,因為如果出現丟失/失序的情況,滑動窗口的左邊緣將會停留在接收到的序號連續的數據的最右的位置,在這種情況下接收到的序號更大的合法數據包,將會被保存起來等待丟失/失序的數據包到達后再提交給應用程序,數據保存后,swSize的值將減小。
3.2 數據包分類
依據接收到的數據包的序號、TSval值、MAX_RECV_SEQ系統變量、MAX_RECV_ACK系統變量和滑動窗口的狀態將它們進行分類。
3.2.1 非法數據包
假設數據包的序號為SEQ,攜帶的數據的字節數為L,符合以下條件之一的數據包被認為是非法數據包:
⑴ 首部ack標志為1,并且符合下列條件之一。
① 攜帶有數據;
② 確認序號小于MAX_RECV_ACK;
③ 序號不處于swLeft-swMax與swLeft+swMax之間。
⑵ 首部的TSval值小于TS_RECENT。這是RFC1323中的PAWS(Protect Against Wrapped Sequence Numbers)[5]要求。
⑶ 序號處于滑動窗口之外,也就是SEQ
3.2.2 失序數據包
指的是攜帶有數據,但是不按順序到達接收方的數據包。這可能是由于延遲、丟失后被重傳等原因造成的。其特點是序號不等于swLeft。
3.2.3 重復數據包
指的是合法的攜帶有數據,但是前面已經成功接收過的數據包,其特點是序號大于等于swLeft-swMax并且序號加上L小于swLeft。重復數據包的作用是為了在接收到后立刻發送一個確認,這與重傳的算法有關。
3.2.4 PZW數據包
這種數據包與在RFC1122中定義的Probing Zero Windows數據包類似,但是實現有所不同,在RUTP中PZW數據包指的是首部的ack和opt標志都為1,且在首部指定了PZW選項的數據包。
3.2.5 數據段
指的是除了上面各種類型之外、攜帶有數據并且按順序到達的合法數據包。
3.3 數據的保存
RUTP協議使用一個接收隊列和一個失序鏈表來保存接收到的數據。接收隊列用于保存接收到的數據包,每個接收到的數據包的序號通過了合法性檢驗后就會被放入接收隊列中,這些數據包按序號的從小到大從隊列的首部開始向后排列。
失序鏈表與接收隊列一起工作,它的表項指向接收隊列的失序位置的下一項,與swLeft一起可以標識出所有的失序情況。
圖4顯示了swLeft、接收隊列和失序表在某一時刻的狀態。
為了支持發送重復確認,失序鏈表的每個表項還會保存其創建時滑動窗口的大小。在發送確認時,如果出現失序的情況就使用第一個表項的滑動窗口的值作為其首部的rwnd字段的值,這樣對于發送方就能符合重復確認的rwnd值相同的要求。
上述設計方式對生成選擇性確認(SACK)信息也有幫助,RUTP的SACK功能與RFC2018中定義的功能相同,但是實現方式有所不同,RUTP中SACK塊是按順序從小到大在首部選項中排序的,而且RUTP的選項沒有TCP的最長40字節的限制。在生成SACK選項的時候只需遍歷一次失序鏈表即可。
3.4 確認的發送
確認指的是接收方發送的、對本方已經接收到的數據的情況起告知作用的數據包,RUTP的確認數據包將首部的ack標志設置為1。RUTP協議在如下幾種情況下會發送確認:
⑴ 接收到失序數據包、重復數據包或PZW數據包都會立刻發送一個確認;
⑵ 連續接收到的未確認字節數大于等于2×RMSS并且滿足式⑴的要求:
swSize>=min(0.5×swMax,RMSS) ⑴
式⑴是為了防止出現RFC1122中定義的糊涂窗口綜合癥(SWS)。
⑶ 確認定時器超時,確認定時器實現的是RFC1122中定義的delayed ACK功能,RFC6298要求延遲的時間必須少于500毫秒[6],超時的時候如果未確認字節數計數器大于0,就會發送一個確認,并且將計數器設置為0,確認定時器只確認以前沒有確認過的數據。創建確認時,其首部各字段的取值如下:
rwnd:如果失序表不為空,就使用第一個表項記錄的滑動窗口值,否則rwnd字段值使用swSize。
acknowledgment:滑動窗口左邊緣swLeft;
sequence:LAST_SEND_SEQ系統變量的值;
TSval:當前時間值;
TSecr:TS_RECENT系統變量的值。
RUTP不會重傳已丟失了的確認,要等到接收到發送方發送的數據包才會繼續發送確認。
4 數據的發送
圖5顯示了數據的發送流程。
4.1 數據包類型
在一個功能完整的發送方,除了可以發送數據段、重傳數據包、發送PZW數據包之外,還必須處理接收到的確認和重復確認,根據RFC5681中的定義,當同時滿足如下條件,一個確認就被認為是一個重復確認[7]:
⑴ 該確認的接收者有發出但未確認的數據;
⑵ 該確認不攜帶有數據;
⑶ 首部syn和fin標志都為0;
⑷ 確認序號等于MAX_RECV_ACK;
⑸ 首部的rwnd值與上一個確認的rwnd值相同。
對于接收方而言,并沒有重復確認這個概念,其所發送的所有確認都是遵循相同的方法創建的,是否重復確認由接收方進行判斷。
4.2 發送過程
從圖5可以看到,如果不滿足發送條件,發送進程將進入等待狀態,在滿足等待發送隊列不為空或發送緩沖區不為空且RWND>0這兩個條件之一,發送進程才被喚醒。
當接收到一個確認后,首先檢查該確認是否攜帶SACK信息,如果有就對未確認隊列進行掃描,將那些被確認的數據包打上被確認(SACKed)標志,避免被重傳,接著從未確認隊列中刪除序號小于確認的ack字段的數據包,因為這些被刪除的數據包已經確定被接收方接收到了。
4.3 擁塞控制
擁塞控制在RFC5681中定義,是發送方的一項重要功能,由慢啟動、擁塞避免、快速重傳和快速恢復功能組成。有兩個用于擁塞控制的變量:
⑴ CWND:發送方在接收到一個響應之前可以發送到網絡的數據的最大字節數。根據RFC5681的定義CWND的初始值IW如下。
如果SMSS>2190字節:
IW=2×SMSS。
如果SMSS>1095字節并且SMSS<=2190字節:
IW=3×SMSS字節。
如果SMSS<=1095字節:
IW=4×SMSS字節。
⑵ SSTHRESH:一個用于判斷是使用慢啟動算法還是擁塞避免算法的閥值,當CWND
開始發送數據的時候由于不了解網絡的擁塞狀況,應該以較慢的速度將數據包發送到網絡中,以避免大量的突發數據包對網絡造成擁塞,這就是慢啟動的目的。
擁塞避免是為了在發現網絡出現擁塞狀況的時候,降低數據包進入網絡的速率。
快速重傳指的是連續接到三個重復確認就立刻重傳序號與該確認的ack字段的值相同的數據包,而不用等到重傳定時器超時。在發生了快速重傳后,就進入了快速恢復的過程而不是重新使用慢啟動算法發送數據包。快速恢復的CWND初始值更大,可以允許更多的數據包進入網絡。
假設N是某個確認數據包確認的字節數,D是接收到的重復確認的個數,接收到確認時擁塞控制的工作流程如圖6所示。
CWND=SSTHRESH? ? ? ? ? ? ? ?⑵
CWND=CWND+min(N,SMSS)? ? ? ⑶
CWND=CWND+max(1,SMSS×SMSS/CWND) ⑷
CWND=CWND+SMSS? ? ? ? ? ? ? ? ⑸
SSTHRESH=max(FLIGHT_SIZE/2,2×SMSS) ⑹
CWND=SSTHRESH+3×SMSS ⑺
另外,如果在重傳定時器超時的時候重傳了數據包,就要執行式⑹和式⑻。
CWND=SMSS? ?⑻
超時重傳之后的發送過程從慢啟動算法開始執行。
4.4 重傳定時器
定時重傳是一個更重要的重傳機制,快速重傳只能根據接收方的提示逐個重傳丟失的數據包,而在重傳定時器中結合SACK機制,一次可以重傳一批數據包,另外PZW數據包也是在重傳定時器中發送的。
重傳定時器的重傳超時時間(Retransmission TimeOut,下稱RTO)使用RFC1323和RFC6298定義的機制進行計算,每接收到一個確認了新數據的確認數據包都會重新計算一次RTO,同時也會重置一次定時器。
4.4.1 RTO的計算
RUTP采用RFC1323定義的RTT測量方法,為此定義了一個系統變量TS_RECENT, 它的值出現在每個發送出去的數據包首部的Tsecr字段中。
假設接收到的數據包序號為SEQ,攜帶的數據字節數為L,如果SEQ<=LAST_SEND_ACK 在接收到一個確認了數據的確認數據包后,將當前時間減去其首部的Tsecr字段值,就可以得到往返時間(round-trip time,下稱RTT),然后根據RFC6298中定義的方法就可以計算出RTO。 4.4.2 工作流程 圖7顯示了重傳定時器的工作流程。 根據RFC2018中的定義,在圖7中被重傳的數據包指的是所有沒有設置SACKed標志且序號小于設置了SACKed標志的數據包的最大序號。 5 結束語 RUTP協議可以用于點對點傳輸數據,也可以用于客戶端/服務器結構的應用之間傳輸數據。RUTP協議目前主要關注的是可靠性、易用性和通用性,應用場景接近于TCP,但是要求能夠應用于某些TCP不適用的場合。經過測試,所有傳輸的數據都能正確到達目的地,沒有出現過傳輸錯誤的情況。在易用性方面,RUTP為應用程序提供了與標準套接字類似的API接口,熟悉套接字編程的程序員可以輕松掌握RUTP協議的使用方法。從應用情況來看,RUTP協議在各方面都能滿足當前需求。 參考文獻(References): [1] 福羅贊著.王海譯.TCP/IP協議族(第4版)[M].清華大學出版社,2011. [2] Information Sciences Institute University of SouthernCalifornia.RFC793 transmission control protocol[S/OL].(1981-9)[2013-5].http://tools.ietf.org/html/rfc0793.html [3] S.Floyd,A.Romanow, M.Mathis,J.Mahdavi.RFC2018 TCPSelective Acknowledgment Options [S/OL].(1996-10)[2013-5].http://tools.ietf.org/html/rfc2018 [4] Internet Engineering Task Force R. Braden.RFC1122Requirements for Internet Hosts-Communication Layers [S/OL].(1989-10)[2013-5].http://tools.ietf.org/html/rfc1122 [5] V.Jacobson,R.Braden.RFC1323 TCP Extensions for?High-Performance[S/OL].(1989-10)[2013-5].http://www.ietf.org/rfc/rfc1323.txt [6] V.Paxson,M.Allman.RFC6298 Computing TCP's Retrans-mission Timer [S/OL]. (2000-9)[2013-5].http://tools.ietf.org/html/rfc6298 [7] M.Allman,V.Paxson,E.Blanton.RFC5681 TCP CongestionControl [S/OL].(2009-9)[2013-5].http://tools.ietf.org/html/rfc5681