国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 網絡通信 > 正文

低速串行鏈路上的TCP/IP頭部壓縮(1)

2019-11-04 10:51:34
字體:
來源:轉載
供稿:網友

1簡介
隨著功能日益強大的計算機進入人們家庭,擴展這些計算機的功能使之與Internet
連接成為日益迫切的要求。不幸的是,這個擴展在鏈路層幀(linklevelframing)、地址
分配(addressassignment)、路由選擇、認證以及性能等方面暴露出很多很復雜的問題。
在寫本文檔時所有這些領域的工作還在進行。本文檔描述一種方法,這種方法已經被用
來提高低速(300-900bps)串行鏈路上的TCP/ip的性能。
這里推薦的壓縮方法與Thinwire-II協議(參考文獻[5])描述的思想是相似的。但是
本協議壓縮的效率更高(壓縮后TCP/IP頭部為3個字節,而Thinwire-II為13個字節),并且
實現起來既高效又簡單(Unix實現需要250行C代碼,在20MHzMC68020中壓縮或者解
壓一個數據包平均需要90μs(_170指令集)。
該壓縮專門針對TCP/IP數據包(注1),作者研究了UDP/IP數據包的壓縮但發現這
種情況極少出現,并且沒有足夠的datagram-to-datagram一致性來進行很好的壓縮(例如,
名字服務器查詢)或者高層協議頭部沉沒了UDP/IP頭部的開銷(例如,Sun'sRPC/NFS)。
作者還研究了分開壓縮數據報的IP和TCP部分,但因為壓縮后頭部平均大小比原來增加
50%,并且壓縮和解壓縮的代碼加倍,因而被否決了。
2問題
人們可能期望通過串行IP鏈路從家中訪問從“終端”擊鍵(type)類型連接(如telnet,
rlogin,xterm)到批量數據傳輸(例如FTP,smtp,nntp)的Internet服務。頭部壓縮的動機就
是出于對良好的交互響應的需要求。也就是說協議的鏈路效率(lineefficiency)為數據
報中header占header+data的百分比。假如高效的批量數據傳輸是我們的目標,,通過把數
據報的尺寸擴大到足夠大總是可以使鏈路效率接近100%。
對人的因素(Human-factor)的研究(參考文獻[15])結果表明交互操作在低層反
饋(feed-back)(字符回顯,characterecho)花費超過100-200ms時被認為是“差的”。協議
頭部從以下幾方面與這個極端交互:
(1)假如鏈路速度太慢,也許不可能把頭部和數據都放在一個200ms的窗口中:每敲
擊一個鍵產生一個字符就要導致發送一個41字節的TCP/IP數據包和接收一個41字節的
反饋(echo)。鏈路速度至少達到4000bps以便在200ms內能夠處理這82個字節的數據
包。







注1:與TCP的聯系(tie)可能比明顯的要強(deeper)。除了壓縮“知道”TCP和IP的頭部,TCP
的某些特征已經被用來簡化壓縮協議。非凡是,TCP的可靠傳輸以及字節流對話模型被本協
議用來消除不必要的錯誤改正對話(見第4章)


Jacobson[Page1]
RFC1144ComPRessingTCP/IPHeadersFebruary1990

(2)即使由一條足夠快的鏈路(大于等于4800bps)來處理擊鍵反饋的數據包,可能
在批量數據和交互流量上產生不想要(undisirable)的交互。為了合理的鏈路效率,要求批
量數據包的大小要達到頭部大小的10--20倍。也就是說,對于40字節的TCP/IP頭部,鏈
路的最大傳輸單元(MTU)應該為500到1000字節。即使服務類型(type-of-service)的排
隊認為交互式業務優先,一個telnet數據包還是得等待當前的批量傳送的數據包傳送結
束,假設數據傳輸僅在一個方向上進行,等待時間為傳輸MTU的一半,對于MTU為1024
字節9600bps的鏈路來說,約為500ms。

(3)任何通信介質都有一個最大信號傳輸速率,即香農極限(AT&T研究結果,參
考文獻[2])。對于典型的撥號電話線香農極限為22,000bps左右。因為全雙工的9600bps
的Modem已經達到了該極限的80%,modem的制造商開始提供不對稱(帶寬)分配方
案來提高有效帶寬:既然一條鏈路鏈路的兩個方向很少同時相同的數據量,就有可能通
過對一條半雙工鏈路進行時分多路復用(例如TelebitTrailblazer),或者提供一條低速的
“反向信道”(例如USRCourierHST)(注2)來給鏈路的一端分配大于11,000bps的帶寬。
在兩種情況下,modem通過假設對話的一方為人(也就是說帶寬要求小于300bps,取決于
擊鍵的速度)動態地試圖猜測對話的哪一端需要更高帶寬。由于協議頭部而導致帶寬乘
以40,從而欺騙這種帶寬分配方案并引起modem“逆風而行”(thrash)。

從上面的討論來看,很明顯,壓縮算法的一個主要設計目標是限制擊鍵(typing)
和確認(ack)流量的帶寬要求最多為300bps。典型的最大擊鍵速度大約為每秒鐘5個字符
(注3),對于每敲擊一個鍵,留下30-5=25個字節給頭部,或者說每敲擊一個鍵就需要
5個字節的頭部(注4),5個字節的頭部直接解決了問題(1)和(3)并間接解決問題(2):長
度為100-200字節的數據包將很輕易償還5個字節頭部的代價并且把鏈路帶寬的95-98%
提供給用戶用于數據部分。


注2:見參考文獻([1],11章)中關于雙絞線撥號線路性能的討論。非凡是,對于
“echo-canclling”modem的(諸如符合CCITTV.32的Modem)性能有很廣泛的誤解:
Echo-cancellation能夠提供給雙絞線的每一端全部的鏈路帶寬,但是,由于遠程用戶的信
號增加了本地噪音,沒有達到線路的全部鏈路性能。22kbs的香農極限是雙絞線電話連
接的數據速率的硬限制(hard-limit)。

注3:見參考文獻[13]。擊鍵流或多字符擊鍵如光標鍵將超過該平均速率(2-4倍)。但
是帶寬要求大致保持不變,因為TCPNagle算法(參考文獻[8])每隔不到200ms對流量
進行統計,提高的頭部/數據比補償了增加的數據。

注4:類似的分析可以得出本質上相同的批量數據傳輸確認(bulkdatatransferack)
的頭部大小限制。假設MTU已經被選來對“不客氣的”(unoBTrusive)后臺文件傳輸(也
就是說,選用數據包發送時間為200-400ms,見第5章),在“高帶寬”方向每秒鐘最多
能傳送5個數據包。合理的TCP實現將最多每隔一個數據包發送一個確認(ack),以便5
字節的ack的反向信道的帶寬為2.5_5_12.5字節/秒。
Jacobson[Page2]
RFC1144CompressingTCP/IPHeadersFebruary1990




這些小的數據包意味著在交互式及批量傳輸之間很少產生沖突(見章節5.2)。

另一個設計目標是壓縮協議僅僅建立在保證串行鏈路的兩端都知道的信息基礎上。
考慮圖1所示的拓撲結構,通信主機A和B在各自的本地網(黑線表示)上,兩個網絡通過
兩條串行鏈路連接(網關C和D之間,及E和F之間的空心線)(注5)。一種可能的壓縮就
是把每一個TCP/IP對話轉變成語義上等價的另一個協議對話,這種協議的頭部比TCP/IP
頭部更小,例如,X.25。但是因為路由的瞬變性(transient)和多路性(multipathing),
完全有可能是A-B的某些流量沿著A-C-D-B路徑而某些流量沿著A-E-F-B路徑。同樣,有
可能A-B的流量沿著A-C-D-B,B-A的流量沿著B-F-E-A。沒有一個網關能指望在一個
具體的TCP對話中看到該對話的所有數據包,圖1的拓撲結構的壓縮算法不能與TCP連接
的語法聯系起來。

把一個物理信道視為兩個獨立的、(每一個方向上)單向的鏈路,對拓撲結構、路
由選擇、流水線操作的要求最小。單向鏈路每一端僅必須在該鏈路最近收到的數據包保
持一致(agreeon)。這樣,雖然任意壓縮方案涉及到共享狀態,但狀態在空間上是臨
時、局部的并且符合DaveClark的fatesharing原則(參考文獻[4]):兩端僅在它們之間
的鏈路連接不可操作時(狀態)才不一致,在這種情況下的不一致并無大礙(doesn't
matter)。




注5:注重雖然TCP的端點為A和B,在本例中壓縮/解壓縮必須在網關之間的串行鏈路上
進行,也就是說在C和D之間以及在E和F之間。因為A和B使用IP,它們不可能知道他們的
通信路徑中包含一段低速串行鏈路,一個很明顯的要求是壓縮不能破壞IP模型,也就是
說壓縮運行在中間系統(intermediate)中而不僅是在端點系統中。




Jacobson[Page3]
RFC1144CompressingTCP/IPHeadersFebruary1990

3壓縮算法
3.1基本思想
圖2顯示了典型的(最小長度的)TCP/IP數據報頭部注6,頭部為40字節:20字節
的IP頭部和20字節的TCP頭部。不幸的是,因為TCP和IP并不是由一個委員會設計的,
頭部中所有這些域都各自用于某個目的,不可能因為效率的原因簡單忽略掉某些域。
但是,TCP建立起連接并且每個連接都進行著幾十甚至幾百個數據包的交換。在整
個連接中每一個數據包有多少信息可能保持不變呢?一半——即圖3中的陰影部分。因
此假如發送者和接收者跟蹤(keeptracKOF)這些活動的連接注7,并且每個連接的接收者
保留上次收到數據包的頭部的拷貝,這樣發送者通過發送一個很小的(≤8位)連接標
識符(connetionidentifier)和變化的20字節,讓接收者從上次保存的頭部中把另外20個
保持不變的字節填入,就可以使數據包壓縮為原來的1/2(afactor-of-twocompression)。
還可以從中提取其它幾個字節。注重到任何合理的鏈路幀協議將告訴接收者所接收
消息的長度,由此TotalLength(第2、3字節)也是多余的;然后,headerchecksum域(第
10和11字節)用來保護各跳(individualhops)不處理“臟的”(corrupted)IP頭部,


注6:TCP和IP協議議及協議頭在參考文獻[10]和[11]中描述。
注7:96位的元組(srcaddress,dstaddress,srcport,dstport)唯一定義了一個TCP連接。

Jacobson[Page4]
RFC1144CompressingTCP/IPHeadersFebruary1990




本質是正在發送的IP頭部的唯一部分。對不是正在傳送的信息的傳送進行保護是可笑的。
所以,接收者可以在頭部被實際發送時檢查headerchecksum(也就是說未壓縮的數據包),
但是,對于壓縮后的數據報文,在IP頭部的其它部分被重構的同時,在本地重構header
checksum注8。

這樣要發送的頭部信息有16字節。所有這些字節在對話的整個過程中都有可能發生
變化但它們不會同時改變。例如在FTP數據傳輸過程中僅僅packetID,sequencenumber
和checksum在發送者——>接收者方向變化,僅有packetID,ack,checksum可能還有
window,在接收者——〉發送者方向發生變化。有了每個方向上上一次發送的數據包的
拷貝,發送者可以算出當前數據包中哪些域發生變化,然后發送一個比特掩碼后跟變化







注8:IP頭部檢驗和并不是參考文獻[14]意義上的端對端檢驗和:time-to-live的更新迫使每一次轉發(hop)
時都要重新計算IP檢驗和。作者曾有很不愉快的個人經歷,因為違反了參考文獻[14]中的端對端的討論
(argument),本協議對端對端的TCP檢驗和未加改變地給予透傳(passthrough)。見第4章。

Jacobson[Page5]
RFC1144CompressingTCP/IPHeadersFebruary1990

的域來表明變化的部分發生了哪些變化(注9)。
假如發送者僅發送變化的域,上面的方案可得到平均10個字節左右的頭部。但是,
值得一看的是這些域的變化情況:典型地,數據包ID由每發送一個包就增加1的計數器
得到,也就是說,當前數據包與前一個數據包的ID之差應該是一個很小的正整數,通常
小于<256(一個字節)并且經常等于1。對于從發送方傳來的數據包,當前數據包中的順序
號(sequencenumber)將等于前一個數據包的順序號加上前一個數據包的數據量(假設
數據包按順序到達)。因為IP數據包最大為64K,順序號的變化必須小于216(兩個字節)。
因此,假如傳送的是變化的域之差(deference)而不是這些域自身,每一個數據包可以節
省另外三四個字節。
這就使我們向5個字節頭部的目標邁進。考慮幾個非凡情況可使我們得到兩種最常
見情形下的3個字節的頭部——交互式擊鍵流量和批量數據傳輸——但基本的壓縮方案
是上面的差分編碼(differentialcoding)。假如這種智力練習表明可以得到5個字節的頭
部,似乎丟失某些細節的信息而真正實現了某些東西應該是合理的。
3.2大致細節
3.2.1綜述
圖4顯示了壓縮軟件的模塊圖。網絡系統調用一個SLIP輸出驅動程序(參數為一個
要在該串行鏈路上發送的IP包)。數據包進入壓縮程序(compressor),壓縮程序檢查
數據包的協議是否TCP。非TCP數據包以及“不可壓縮的”(“uncompressible”)TCP
數據包(如后面所述)僅被標記為TYPEIP并傳送到成幀器(framer)。對于可壓縮的TCP數
據包,則在數據包頭部陣列中查找(與之匹配的連接)。假如找到匹配的連接,則進來
的(incoming)數據包被壓縮,(未壓縮之前的)數據包頭部被拷貝到陣列中,類型為
COMPRESSEDTCP的數據包被送到framer。假如沒有找到匹配的連接,陣列中最舊的
(oldest)表項(entry)被廢棄,數據包的頭部被拷貝到該槽(slot)中,并且把一個類
型為UNCOMPRESSEDTCP的數據報送到成幀器。(UNCOMPRESSEDTCP數據包與初始
IP包相同,除了IPprotocol域被一個到已保存的每個連接的數據包頭部陣列的索引
connectionnumber取代之外。這就是發送者與接收者(重新)同步,并把它作為壓縮數據
包序列的第一個未壓縮數據包的“種子”(seed)的方法。
framer負責傳送該數據包的數據,類型以及邊界(boundary)(以便解壓程序知道壓
縮程序產生的字節數)。因為編碼是差分編碼(differentialcoding,),不答應framer對數
據包進行重新排序(在一個單獨的串行鏈路上很少需要考慮)。framer必須提供良好的

注9:這與Thinwire-I(參考文獻[5])大致相同。一個稍微的改變是增量編碼("deltaencoding"),
即發送者從當前數據包減去前一個數據包(每一個數據包視為16位整數的陣列),然后發送一
個20-bit的掩碼表明差(deference)為非0的各域(后跟變化內容)。假如分離不同的對話,
這是一個非常有效的壓縮方案(也就是說,典型的得到12-16字節的頭部),壓縮方不涉及數據
包的包格式細節。這種方案的多個變種已經被成功使用了很多年(例如Proteon路由器的串行
鏈路協議,參考文獻[3])。
Jacobson[Page6]
RFC1144CompressingTCP/IPHeadersFebruary1990

錯誤檢測能力并且假如connectionnumber被壓縮,它還必須向解壓程序提供錯誤暗示
(errorindication,見第4章)(注10)。
解壓程序在進來的(incoming)數據包的類型來一個'switch':對于TYPEIP,數據包被
簡單地透傳(passthrough);對于UNCOMPRESSEDTCP,連接號(connectionnumber)
從IPprotocol域中提取(extracted),IPPROTOTCP被存儲,然后連接號被用來作為接
收方所保存的TCP/IP頭部陣列的索引值,數據包的頭部被拷貝到該索引所對應的槽中。
對于COMPRESSEDTCP,連接號用來作為得到該連接上一個數據包的TCP/IP頭部的索
引值,壓縮數據包中的信息用來更新(上一個數據包的)頭部,然后構建一個新的數據
包(包含從陣列中得到的頭部,連接從壓縮數據包中取得的數據。)
注重通信是單向的——解壓程序到壓縮程序的方向上沒有信息流。非凡地,隱含著
解壓程序依靠TCP的重傳來在發生鏈路錯誤(lineerrors)時改正已保存的狀態(見4)。



3.2.2壓縮數據包格式
圖5顯示了壓縮后TCP/IP數據包的格式。其中changemask標識了預期變化的哪些域
發生了變化,connectionnumber使得接收方能夠定位該TCP連接的上一個數據包的拷貝





注10:鏈路幀超出本文檔的范圍。任何幀只要提供了本段中列出的功能(facility),對于本壓
縮協議應該是足夠的。但是作者鼓勵實現者參照參考文獻[9]的一個推薦的標準的SLIP幀。


Jacobson[Page7]
RFC1144CompressingTCP/IPHeadersFebruary1990



所存放的位置,不變的TCP檢驗和使得端到端的完整性檢查依然有效,對于changemask
中設置的位,相關域的變化量(可選的域,由改變掩碼控制,在圖中用虛線表示)。所有
情況下,假如相關的域出現時該位設置為1,假如相關的域不出現則該位為0注11。
因為sequencenumber等的改變量一般都很小,非凡是遵循第5章的調節(tuning)原
則時,所有的數字實際上按一個可變長度方案編碼,該方案用8位控制大部分的業務:1
—255的改變量用一個字節來表示,0是不可能出現的(改變量為0則不發送),所以為0
的字節表明一種擴展:接下去的兩個字節為16位值的MSB和LSB。大于16位的值強迫發
送為未壓縮包。例如15(十進制)編碼為0f(十六進制),255編碼為ff,65534為00fffe,
而0編碼為000000。這種方案的壓縮和解碼效率很高:通常情況下在MC680x0上編
碼和解碼都需要執行3條指令。
作為TCP序列號以及ack發送的數值為當前數據包與前一個數據包中的值之差(如
果差為負或大于64K則發送未壓縮數據包)注12。作為window發送的值也是當前值與前




注11:圖中“P”位與其它位不同:它是TCP頭部的"PUSH"位的拷貝。"PUSH"曾被Internet
協會中的某些人認為是必不可少的。因為PUSH能(實際上也)在任何數據包中改變,
因此保留信息的壓縮方案必須顯式的傳送(pass)PUSH。
注12:所有的差使用2'scomplementarithmetic計算。



Jacobson[Page8]
RFC1144CompressingTCP/IPHeadersFebruary1990

一個值之差,但是正負值都答應,因為window域為16位。在設置URG時發送數據包的緊
急事件指針(假如緊急事件指針發生改變而沒有設置URG位時發送未壓縮數據包)。對于
packetID,發送的值為當前值與前一個值之差。但與域中其它部分不同,當清除I位時假
定的變化值為1,而不是0。
有兩種很重要的非凡情況:
(1)sequencenumber和ack都改變(改變值為上個數據包的數據量);window和URG
均不變。
(2)sequencenumber改變(改變值為上個數據包的數據量);ack,window和URG
均不變。
(1)就是終端反饋流量(echoedterminaltraffic)的情況。(2)是非終端反饋流量或單向
數據傳輸的情況。S,A,W,U的組合用來表明這些非凡情形。'U'(urgentdata)很少出現,
所以兩種不太可能的組合是SWU(情形1)和SAWU(情形case2)。為避免二義性,假如
實際改變值是S*WU,則發送未壓縮數據包。
因為“活動的”('active')連接很少改變(也就是說用戶在換到另一個窗口前將在
一個telnet窗口擊鍵幾分鐘),C位答應連接號被忽略掉。假如清除了C位,則假設與上一
個壓縮或未壓縮的數據包是一樣的連接;假如設置了C位,則連接號就是緊跟在change
mask后面的那一個字節注13。
從上面的討論得知,很明顯壓縮后的終端流量通常看起來像(十六進制):0Bcc
d,0B表明情形(1),cc是兩個字節的TCP檢驗和,d是所敲擊的鍵。命令vir或emacs,或
者FTP“put”或“get”數據傳輸方向的數據包看起來為0Fccd...,該FTP的ack看起
來為04cca,其中a為被確認的數據量注14。
3.2.3壓縮過程(Compressorprocessing)
由待壓縮IP數據包和輸出串行線的“壓縮狀態結構”調用壓縮程序。它返回的是最
終成幀(framing)的數據包以及該數據包的鏈路層“類型”。


注13:連接號限制為一個字節,即同時最多能有256個活動的TCP連接。在將近兩年的操作
中,作者從沒有看到超過16個連接狀態的情形有什么用處(即使在SLIP鏈路用于一個
很繁忙的64-port的終端復用器的網關時也是如此)。這樣看來這個限制沒有多大意義,
這就答應UNCOMPRESSEDTCP數據包使用protocol域作為連接號,以簡化這些數據
包的處理過程。
注14:也很明顯changemask很少改變,經常可被忽略。實際上,可以通過保存上一個壓縮
數據包(最多為16字節,因此thisisn'tmUChadditionalstate)并檢查(除了TCP檢驗和)是否
發生變化,而得到更好的結果。假如沒有變化,發送一個意思為"壓縮TCP,與上次相同"的數
據包和一個僅包含檢驗和和數據的數據包。但是,由于改進最多為25%,增加的復雜性和狀
態結構似乎并不可行(justified)。見附錄C。



Jacobson[Page9]
RFC1144CompressingTCP/IPHeadersFebruary1990

正如上一節提到的那樣,壓縮程序把進來的每一個數據包轉換成TYPEIP,
UNCOMPRESSEDTCP或者COMPRESSEDTCP數據包。TYPEIP數據包是輸入數據包未
加修改的拷貝注15,處理它不會改變壓縮程序的狀態。
UNCOMPRESSEDTCP數據包除了IPProtocol(第9個字節)從‘6’(TCP協議)改
為連接號connectionnumber外與輸入數據包相同。另外,與連接號關聯的狀態槽被輸入
數據包的IP和TCP頭部更新,連接號記為本串行鏈路的lastconnectionsent(對下面的C
壓縮程序而言)。
COMPRESSEDTCP數據包包含初始數據包的數據(假如初始數據包有數據的話),
但是IP和TCP頭部已完全被一個新的經過壓縮的頭部取代,連接狀態槽和lastconnectionsent
被輸入數據包中像UNCOMPRESSEDTCP那樣更新。
壓縮程序的決定過程為:
● 假如數據包的協議不是TCP,把它作為一個TYPE_IP數據包發送。
● 假如數據包是一個IP分片(即fragmentoffset域不為0或設置morefragments位),
把它作為TYPEIP數據包發送。注16
●假如設置了TCP控制位SYN,FINorRST或者ACK為0,把該數據包視為不可壓
縮,把它作為TYPE_IP發送。注17

假如數據包通過了上述檢查,它將被作為UNCOMPRESSEDTCP或COMPRESSED
TCP發送。
● 假如沒有找到與數據包的源地址、目的IP地址及TCP端口號匹配的連接狀態,
將收回某狀態(可能為最近最少使用的),發送一個UNCOMPRESSEDTCP。

.
注15實際上不必要(也不想)為三種輸出數據包中的任一種復制輸入數據包。注重壓縮器
不能增加一個數據報的大小。正如附錄A中的代碼顯示的那樣,本協議能“就地”(in
place,取代式地)完成頭部的修改。
注16僅僅第一個分片包含TCP頭部所以分片偏移量的檢查是必要的。第一個分片可能包
含一個完整的TCP頭部,因而,可以被壓縮。但是檢查一個完整的TCP頭部增加很多代
碼,按照參考文獻[6]中的討論,未經壓縮地發送所有IP分片似乎是合理的。
注17 ACK檢查是多余的,因為符合標準的實現必須在所有數據包中設置ACK,除了初
始的SYN數據包以外。但是,該檢查不花任何代價并且避免把一個假(bogus)的數據包
變成一個有效的數據包。
SYN數據包不壓縮是因為僅有一半包含有效的ACK域并且他們通常包含一個TCP
選項(最大分段大小,themaxsegmentsize),而在以后的數據包中沒有該選項。這樣下
一個數據包將不經壓縮便發送,因為TCP頭部長度已經改變,而發送SYN為
UNCOMPRESSEDTCP,而不是TYPEIP,將不花任何代價(wouldbuynothing)。
決定不對FIN數據包進行壓縮值得質疑。對附錄B.1中的技巧打一下折扣,頭部中有
一個空閑位可用來傳送FIN標志。但是,因為連接過程中傳送很多數據包,把一個
比特賦予在連接的生存期僅出現一次的標志似乎不太合理。


Jacobson[Page10]
RFC1144CompressingTCP/IPHeadersFebruary1990

● 假如找到一個連接狀態,則比較其所包含的數據包頭部與當前的數據包頭部以確保
沒有出現實現沒有預料的變化(舉例說來,圖3中所有的陰影域都一樣)。檢查IP
protocol,fragmentoffset,morefragments,SYN,FIN以及RST域,檢查源、
目的地址及端口號以定位狀態結構所處的位置。所以剩下要檢查的域是
protocolversion,headerlength,typeofservice,don'tfragment,
time-to-live,dataoffset,IP選項(假如有)和TCP選項(假如有)。假如兩者頭
部中任一個域不同,則發送UNCOMPRESSEDTCP數據包。

假如所有的“不改變"域匹配,將試圖對當前數據包進行壓縮:
——假如設置了URG標志,urgentdata域被編碼(注重可能為0),設置改變掩碼中
的U位。不幸的是,假如URG被清除,urgentdata域必須與前一個數據包進行比
較,假如發生改變,則發送UNCOMPRESSEDTCP數據包。(“Urgentdata”在
URG被清除時不應該改變,但參考文獻[11]不作這樣的要求)。
——計算當前數據包與前一個數據包中window域之差,假如非0,差被編碼并且設置
changemask中的W位。
——計算ack域之差,假如結果小于0或者大于216-1,發送一個UNCOMPRESSEDTCP
數據包注18。否則,假如結果為非0,差被編碼,設置changemask中的A位。
——計算sequencenumber域之差。假如結果小于0或大于216-1,發送UNCOMPRESSED
TCP數據包注19。否則假如結果為非0,被編碼且設置changemask中的S位。

一旦判定出U,W,A和S發生改變,檢查非凡情形的編碼:
--假如設置了U,S和W,改變量符合非凡編碼的一種情形。發送一個
UNCOMPRESSEDTCP數據包。
--假如僅設置S,比較改變量是否等于最后一個數據包中的用戶數據。即從
上一個數據包中的totallength中減去TCP和IP頭部長度,將結果與S的改
變量進行比較。假如它們相同,設置changemask為SAWU(“單向數據傳輸”
的非凡情形),并丟棄編碼后的sequencenumber改變(壓縮程序可以重建
它,因為它知道最后一個數據包的總長度和頭部長度)。







注18.這兩個比較(test)可以合并為最高有效16位的差是否為非0。
注19.改變量為負的sequencenumber暗示著可能是一次重傳。因為這有可能是因為壓縮程序
丟失了一個數據包,所以發送一個未壓縮數據包以對解壓器進行重同步(re-sync,見4)。



Jacobson[Page11]
RFC1144CompressingTCP/IPHeadersFebruary1990

——假如僅設置了S和A,檢查是否它們的改變量是否相同,并且該變量是否
等于最后的數據包中的用戶數據量。假如這樣,設置changemask為
SWU(“回顯交互式”流量的非凡情形),并丟棄已編碼的改變量。
——假如什么都沒有改變,檢查是否該數據包沒有用戶數據(這種情況可能
是一個重復的確認或窗口檢測windowprobe),或者前一個數據包是否包
含用戶數據(意味著該數據包是非流水線連接上重傳數據包
retransmissiononaconnectionwithnopipelining)。在這兩種情況下,發
送一個UNCOMPRESSEDTCP數據包。

最后,輸出數據包的TCP/IP頭部被(壓縮程序產生的)壓縮頭部取代。
——計算packetID的變化,假如不是1注20,差被編碼(注重可能為0或負數)并
設置改變掩碼的I位。
——假如最初數據包中設置PUSH位,設置改變掩碼中的P位。
——數據包的TCP和IP頭部被拷貝到連接狀態槽(connectionstateslot)中。
——(最初)數據包的頭部被丟棄,新的頭部被添加到前面(prepended)。包括(以
倒序):
–累積的變化量編碼。
–TCPchecksum(假如新的頭部“就地”(inplace,取代式地)創建,checksum
有可能已經被覆蓋,必須從最初的頭部被丟棄之前拷貝到連接狀態結構中或
者臨時保存的拷貝中獲取。
–connectionnumber(假如與該串行鏈路上最后一次發送的不同)。這也意味著
該鏈路的lastconnectionsent必須設為connectionnumber并在改變掩碼中設
置C位。
–改變掩碼(changemask)
這時候,壓縮的TCP數據包傳到成幀器(framer)以待發送。
3.2.4解壓過程
因為這是一個單向通信模型,解壓程序的處理過程比壓縮程序的處理過程要簡單的
多——所有的判定(decisions)已經決定好了,解壓程序只要簡單地按照壓縮程序叫它
做的工作。



注20.注重是與1而不是與0進行比較。packetID典型的是每發送一個數據包增1,所以該變
量為0的情況是不太可能出現的。改變量為1的情況是可能的:在系統僅在一個連接上有活動
時發生。




Jacobson[Page12]
RFC1144CompressingTCP/IPHeadersFebruary1990

解壓程序由輸入數據包注21,數據包的類型以及輸入串行鏈路的壓縮狀態結構調
用。返回一個(可能被重新構建的)IP數據包。
解壓器可接收4種類型的數據包:由壓縮程序產生的三種包以及當幀接收器檢測到
錯誤(注22)時所產生的一個TYPE_ERROR假(pseudo-)數據包。第一步是對這些數據
包類型來一個“switch”:
● 假如數據包為TYPEERROR或者未知的類型,狀態結構中設置一個“丟棄”
('toss')標志以迫使COMPRESSED_TCP數據包被丟棄,直到收到設置C位的數
據包或者一個UNCOMPRESSEDTCP數據包。不返回任何東西(空數據包)。
● 假如數據包為TYPE_IP,不加改變地返回它的拷貝并且狀態結構不改變.
● 假如數據包為UNCOMPRESSEDTCP,檢查IPProtocol域的狀態索引(注23)。如
果非法,設置“丟棄”標志,不返回任何值。否則,清除“丟棄”標志,索引被拷
貝到狀態結構的lastconnectionreceived域,創建輸入數據包的一份拷貝(注
24)。TCPprotocol號被恢復(restore)到IPprotocol域,數據包頭部被拷貝到
(索引)表明的狀態槽中,返回數據包的拷貝。

假如數據包類型不在上面討論之中,它就是COMPRESSEDTCP,必須由數據包的
信息和狀態槽中上一個數據包頭部合成一個新的TCP/IP頭部。首先,顯式或隱式的
connectionnumber用來定位狀態槽:
——假如改變掩碼中設置了C位,那么檢查狀態索引。假如非法,設置“丟棄位”
標志,不返回任何值。否則,lastconnectionreceived設為該數據包的狀態索
引值,清除“丟棄”位。
——假如C位被清除(為0),并且設置了“丟棄”位標志,該數據包被忽略,不
返回任何值。
此時,lastconnectionreceived是適當的狀態槽的索引,壓縮數據包的第一個(頭
幾個)字節(改變掩碼,可能還有連接索引connectionindex)已經被消化掉(consumed)。


注21.假設鏈路層framing此時已被去除,數據包和length不包括type或framing字節數。
注22.TYPEERROR數據包不需與任何數據相關。它之所以存在是為了使幀接收器能告訴
解壓程序數據流中可能有斷點(gap)。解壓器使用TYPE_ERROR通知(signal)解壓程序:數
據包應該被丟棄直到一個有顯式連接號(connectionnumber)的數據包(即設置了C位)到達。
這樣做的必要性見4.1節最后的討論。
注23.狀態索引遵循C語言的習慣,從0到N-1,0<N≤256是可用狀態槽的索引。
注24.對于壓縮程序來說,可以對代碼進行結構化(structured)以便不需要拷貝,所有的修改
都是“取代式”(inplace)的。但是,因為輸出數據包可能比輸入數據包大,必須在輸入
數據包緩沖區的前部保留128個字節的空間以答應放入TCP/IP頭部。





Jacobson[Page13]
RFC1144CompressingTCP/IPHeadersFebruary1990

因為狀態槽中的TCP/IP頭部必須終結以反映新到來的數據包,把這些數據包的改變量
應用于頭部,然后由頭部連接(concatenate)輸入數據包的數據從而構建出輸出數據包
是最簡單的。(在下面的描述中“已保存頭部”用作“保存在狀態槽中的TCP/IP頭部”
的縮略語)
——輸入數據包中接下來兩個字節是TCP檢驗和。它們被拷貝到“已保存頭部”中。
——假如改變掩碼中設置了P位,“已保存頭部”中設置TCPPUSH位。否則清除
PUSH位。
——假如改變掩碼的低4位(S,A,W和U)都設置為1(“單向數據”的非凡情形),上
一個數據包的用戶數據量通過從“已保存頭部”中的IPtotallength中減去TCP
和IP頭部長度計算得到。該用戶數據量(計算的結果)被加到“已保存頭部”
的TCPsequencenumber中。
——假如設置了S,W和U,但清除了A(“終端流量”非凡情形),上一個數據包的
用戶數據量被計算并被加到“已保存頭部”中TCPsequencenumber和ack域中。
——否則,改變掩碼的各位按壓縮程序設置的順序解釋:
—假如設置了U位,在“已保存頭部”中設置TCPURG位,輸入數據包接下
來的字節被解碼并填充到到TCPUrgentPointer中。假如清除了U位,則清
除TCPURG位。
—假如設置了W位,輸入數據包中接下來的字節被解碼并被添加到“已保存
頭部”中的TCPwindow域。
—假如設置了A位,輸入數據包接下來的字節被解碼并被添加到“已保存頭部”
的TCPack域中。
—假如設置了S位,輸入數據包中接下來的字節被解碼并被加到“已保存頭部”
的TCPsequencenumber域中。

——假如改變掩碼設置了I位,輸入數據包接下來的字節被解碼并被加到已保存數
據包的IPID域。否則IPID.加1。

至此,輸入數據包中的所有頭部信息被消耗(consumed)完畢,僅剩下數據部分。
剩下的數據部分的長度與已保存TCP和IP頭部的長度相加,結果放入已保存IPtotal
length域中。已保存IP頭部現已被更新,故其檢驗和被重新計算并被保存到IPchecksum
域中。最后,包括“已保存頭部”與剩下的輸入數據的輸出數據報被構建并返回。










Jacobson[Page14]
RFC1144CompressingTCP/IPHeadersFebruary1990
4錯誤處理
4.1錯誤檢測
根據作者的經驗,撥號連接非凡輕易出現數據錯誤。這些錯誤與壓縮從兩方面交互:
首先是已壓縮數據包中的錯誤的局部(local)影響。所有的錯誤檢測建立在數據冗
余基礎上,但壓縮幾乎擠出了TCP和IP頭部中的全部冗余數據。也就是說,解壓程序將
很樂意把隨機的鏈路噪音變成一個有效的TCP/IP包(注25)。人們可以根據TCP檢驗和
檢測“臟的”(“corrupted”)的壓縮數據包,但是不幸的是,某些很有可能發生的錯
誤不會被檢測到。例如,TCP檢驗和經常不會檢測到被16位分開的2個單獨的比特的錯
誤。對于V.32modem以2400波特率,4bits/baud發送信號,任意持續超過40us的鏈路
瞬時干擾(linehit)將破壞16比特。按照參考文獻[2],住宅電話的鏈路瞬時干擾有可能達
到2ms。
處理這個問題的正確方法是在鏈路層提供錯誤檢測。因為framing(至少在理論上)
可以處理使之符合特定鏈路上的某些特性,檢測可以根據該鏈路作為輕權或重權(注
26)。因為數據包錯誤檢測是在幀級別上進行,解壓程序簡單的假設它會收到當前接收
的數據包有錯誤的暗示(解壓器總是忽略(丟棄)有錯誤的數據包,但是,需要有暗示
來防止錯誤被進一步傳播——見下面)。
“丟掉錯誤的數據包”策略引起錯誤和壓縮的第二種交互。考慮下面的對話:
Orignal
Sent
Recived
reconstucted
1:A
2:BC
4:DE
6:F
7:GH
1:A
Δ1,BC
Δ2,DE
Δ2,F
Δ1,GH
1:A
Δ1,BC
——
Δ2,F
Δ1,GH
1:A
2:BC
——
4:F
5:GH
(上面的每個表項都有“startingsequencenumber:datasent”或“Δ_sequencenumber
change,datasent”的格式)。發送的第一個數據包是一個未壓縮數據包,跟著的是四個
壓縮數據包。第三個數據包出現一個錯誤并被丟棄。為重構第4個數據包,接收者把輸
入的壓縮數據包中的sequencenumber變化量應用到上一個正確接收的數據包(即第2個
數據包)的sequencenumber上,產生第4個數據包的不正確的sequencenumber。在錯誤



注25:模(modula)TCP檢驗和。
注26:雖然合適的錯誤檢測方法依靠于鏈路,參考文獻[9]中使用的CCITTCRC在很多鏈路
上取得了計算的簡易性和錯誤檢測的健壯性(robust)之間的完美的平衡,尤其是為了好的
交互響應而需要相對小的數據包時。這樣,由于互操作性的原因,除非有強有力的原因以外,
應該使用參考文獻[9]中的幀(格式)。
Jacobson[Page15]
RFC1144CompressingTCP/IPHeadersFebruary1990

出現之后,所有重建數據包的sequencenumber將都是錯誤的,均比正確值減小所丟失數
據包的數據量(注27)。
假如沒有某種類型的檢查,前述錯誤將導致接收者在傳輸過程中看不見丟失了的兩
個字節(因為解壓器重新產生sequencenumber,包含F和GH的數據包到達接收者時將有
正確的sequencenumber,假如DE數據包不曾存在)。雖然TCP對話可以在丟失數據后繼
續存活(注28),但是不鼓勵這么做。幸運的是,由于TCP檢驗和是一個數據包內容(包
括sequencenumber)的簡單和(singlesum),它可以百分之百地檢測到這種錯誤。例
如,上面的接收方計算出的最后兩個數據包的檢驗和,總是與數據包的檢驗和相差2。
不幸的是,假如輸入壓縮數據包(incomingcompressedpacket)的變化量被應用到
錯誤的對話時,總是有辦法令上面所講的的TCP檢驗和失效:考慮兩個活動對話C1和C2,
一個從C1來的數據包后面跟著兩個來自C2的數據包。因為連接號沒有改變,則連接號
被C2的第二個數據包省略(omitted)掉。但是,假如C2的第一個數據包接收時發生CRC
錯誤,則C2的第二個數據包將被錯誤的當成C1的第二個數據包。因為對于C1的sequence
number來說,C2的檢驗和是一個隨機數,至少有2-16的概率使得該數據包被C1的TCP
接收方接收(注29)。為防止這種情況發生,在收到來自成幀器(framer)的CRC錯誤
暗示后,接受方丟棄數據包直到收到一個設置了C位的COMPRESSEDTCP數據包或者是
一個UNCOMPRESSEDTCP數據包。也就是說,數據包被丟棄直到接收到帶顯式
connectionnumber的數據包。
總結本節,有兩種不同的錯誤類型:數據包的“變質”(corruption),和會話同步
的喪失(loss-of-sync)。第一種類型解壓器方通過鏈路層CRC錯誤檢測到,第二種在TCP
接收方通過一個(保證)有效的TCP檢驗和檢測到。這兩種獨立機制的聯合使用確保了
錯誤數據包被丟棄。
4.2錯誤恢復
前面章節提到,在CRC錯誤之后解壓器將在每一個未壓縮數據包中引進TCP檢驗和
錯誤。雖然檢驗和錯誤防止了數據流的變質(corruption),在解壓器產生出一個有效的
數據包之前該TCP對話將不可用。這是怎樣發生的呢?
解壓器產生無效的數據包是因為其狀態結構(已保存的“上一個數據包頭部”)與
壓縮器的狀態結構不一致。一個UNCOMPRESSEDTCP數據包將修正解壓器的狀態。這樣,
錯誤恢復等于在解壓器在感到混亂(confused)時迫使壓縮器發送一個未壓縮數據包。





注27:這是使用差分編碼或增量編碼時一個普遍的問題的一個實例,稱為"losingDC"。
注28.很多系統治理員聲稱NNTP數據流中的漏洞(holes)比數據更有價值(morevaluable)。
注29.在最差情況下的流量下,該概率理解為一條9600波特率,錯誤率為30%的鏈路上每3
個小時就有一個錯誤沒有被檢測出來。

Jacobson[Page16]
RFC1144CompressingTCP/IPHeadersFebruary1990




首先要考慮的是利用全雙工通信鏈路,讓解壓器請求壓縮器發送一個非壓縮數據
包。很顯然這是我們不想要的,因為它包含的拓撲結構比第2章中建議的最小拓撲結構
復雜得多,并且要求給解壓器和壓縮器增加很多協議。稍加考慮就可以知道這種選擇不
僅僅是我們不想要的,它簡直就無法工作(奏效):壓縮數據包很小,以至于鏈路瞬時
干擾(linehit)可能把它完全沉沒,最終解壓器什么也沒收到。這樣數據包被錯誤地重
構(因為壓縮包的丟失),但是僅有TCP端(end)知道數據包是錯誤的,解壓器根本不
知道。
但是,既然TCP端知道該錯誤,而TCP設計為運行在不可靠介質上的可靠協議,這
就意味著TCP兩端必須最終采取某種錯誤恢復措施,壓縮器必須有明顯的觸發器以對解
壓器進行重新同步:TCP進行錯誤恢復時發送一個非壓縮包。
但是壓縮器怎樣才能認出這是TCP錯誤恢復呢?考慮圖6中的TCP數據傳輸示意圖。
感覺到混亂的(confused)解壓器處于TCP對話的前向部分(即數據傳輸部分)。TCP
接收方丟掉數據包而不是對它們進行確認(因為檢驗和出錯),TCP發送方最終超時并
重發數據包,前向中的壓縮器發現重傳數據包的sequencenumber和它所看到的上一個數
據包的sequencenumber之差為負數(假如有幾個數據包通過)或者0(只有一個數據包通


Jacobson[Page17]
RFC1144CompressingTCP/IPHeadersFebruary1990





過)。第一種情況在壓縮階段計算序列號之差的步驟檢測到。第二種情況在檢查“非凡
情形”編碼階段檢測,但還要求另一個檢查:交互式對話中經常先發送一個無數據的ack
再發送一個包含數據的數據包,ack和包含數據的數據包有相同的sequencenumber但是
數據包卻不是(該ack的)重傳。為防止發送一個不必要的未壓縮數據包,應該檢查前
一個數據包的長度,假如它包含數據,sequencenumber變化量為0則肯定(must)意味
著重傳。
圖7中會話的反向部分鏈路(即確認方向)上感到混亂的解壓器也很輕易檢測到:
TCP發送方丟掉ack(因為它們包含檢驗和錯誤),最終超時,然后重傳某數據包。這樣TCP
接收方就收到重復的數據包,它必須發送一個ack以指明期望的下一個sequencenumber。
值產生一個ack(參考文獻[11],p.69)。該ack重復了TCP接收方產生的上一個ack,所
以反向的壓縮器將發現ack,seqnumber,window或urg沒有改變。假如這發生在不包含數
據部分的數據包上,壓縮器就會假設它是對應于重傳而發送的重復的ack,因而發送一
個UNCOMPLESSEDTCP數據包(注30)。





注30:該數據包可以為一個0-窗口檢測而不是重傳ack,但窗口檢測不應太頻繁,未壓縮便
發送它們沒有壞處

Jacobson[Page18]
RFC1144CompressingTCP/IPHeadersFebruary1990




發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 五指山市| 晋中市| 湄潭县| 和平区| 葵青区| 乌苏市| 夏河县| 镇江市| 荥经县| 大英县| 广西| 资溪县| 荆门市| 丰城市| 若尔盖县| 炉霍县| 和平县| 乌拉特后旗| 牙克石市| 恭城| 育儿| 中牟县| 时尚| 兖州市| 嵩明县| 永宁县| 唐山市| 五峰| 宜川县| 永年县| 黄龙县| 色达县| 海南省| 黑水县| 襄城县| 万盛区| 襄城县| 花垣县| 黄大仙区| 乌兰浩特市| 攀枝花市|