當前在網路傳輸應用中,廣泛採用的是tcp/ip通訊協議及其標準的socket應用開發程式設計介面(api)。tcp/ip傳輸層有兩個並列的協議:tcp和udp。其中tcp(transport control protocol,傳輸控制協議)是面向連線的,提供高可靠性服務。udp(user datagram protocol,使用者資料報協議)是無連線的,提供高效率服務。在實際工程應用中,對可靠性和效率的選擇取決於應用的環境和需求。一般情況下,普通資料的網路傳輸採用高效率的udp,重要資料的網路傳輸採用高可靠性的tcp。
在應用開發過程中,筆者發現基於tcp網路傳輸的應用程式有時會出現粘包現象(即傳送方傳送的若干包資料到接收方接收時粘成一包)。針對這種情況,我們進行了專題研究與實驗。本文重點分析了tcp網路粘包問題,並結合實驗結果提出了解決該問題的對策和方法,供有關工程技術人員參考。
一、tcp協議簡介
tcp是乙個面向連線的傳輸層協議,雖然tcp不屬於iso制定的協議集,但由於其在商業界和工業界的成功應用,它已成為事實上的網路標準,廣泛應用於各種網路主機間的通訊。
作為乙個面向連線的傳輸層協議,tcp的目標是為使用者提供可靠的端到端連線,保證資訊有序無誤的傳輸。它除了提供基本的資料傳輸功能外,還為保證可靠性採用了資料編號、校驗和計算、資料確認等一系列措施。它對傳送的每個資料位元組都進行編號,並請求接收方回傳確認資訊(ack)。傳送方如果在規定的時間內沒有收到資料確認,就重傳該資料。資料編號使接收方能夠處理資料的失序和重複問題。資料誤碼問題通過在每個傳輸的資料段中增加校驗和予以解決,接收方在接收到資料後檢查校驗和,若校驗和有誤,則丟棄該有誤碼的資料段,並要求傳送方重傳。流量控制也是保證可靠性的乙個重要措施,若無流控,可能會因接收緩衝區溢位而丟失大量資料,導致許多重傳,造成網路擁塞惡性迴圈。tcp採用可變視窗進行流量控制,由接收方控制傳送方傳送的資料量。
tcp為使用者提供了高可靠性的網路傳輸服務,但可靠性保障措施也影響了傳輸效率。因此,在實際工程應用中,只有關鍵資料的傳輸才採用tcp,而普通資料的傳輸一般採用高效率的udp。
二、粘包問題分析與對策
tcp粘包是指傳送方傳送的若干包資料到接收方接收時粘成一包,從接收緩衝區看,後一包資料的頭緊接著前一包資料的尾。
出現粘包現象的原因是多方面的,它既可能由傳送方造成,也可能由接收方造成。傳送方引起的粘包是由tcp協議本身造成的,tcp為提高傳輸效率,傳送方往往要收集到足夠多的資料後才傳送一包資料。若連續幾次傳送的資料都很少,通常tcp會根據優化演算法把這些資料合成一包後一次傳送出去,這樣接收方就收到了粘包資料。接收方引起的粘包是由於接收方使用者程序不及時接收資料,從而導致粘包現象。這是因為接收方先把收到的資料放在系統接收緩衝區,使用者程序從該緩衝區取資料,若下一包資料到達時前一包資料尚未被使用者程序取走,則下一包資料放到系統接收緩衝區時就接到前一包資料之後,而使用者程序根據預先設定的緩衝區大小從系統接收緩衝區取資料,這樣就一次取到了多包資料(圖1所示)。
圖1圖2
圖3 粘包情況有兩種,一種是粘在一起的包都是完整的資料報(圖1、圖2所示),另一種情況是粘在一起的包有不完整的包(圖3所示),此處假設使用者接收緩衝區長度為m個位元組。
不是所有的粘包現象都需要處理,若傳輸的資料為不帶結構的連續流資料(如檔案傳輸),則不必把粘連的包分開(簡稱分包)。但在實際工程應用中,傳輸的資料一般為帶結構的資料,這時就需要做分包處理。
在處理定長結構資料的粘包問題時,分包演算法比較簡單;在處理不定長結構資料的粘包問題時,分包演算法就比較複雜。特別是如圖3所示的粘包情況,由於一包資料內容被分在了兩個連續的接收包中,處理起來難度較大。實際工程應用中應盡量避免出現粘包現象。
為了避免粘包現象,可採取以下幾種措施。一是對於傳送方引起的粘包現象,使用者可通過程式設計設定來避免,tcp提供了強制資料立即傳送的操作指令push,tcp軟體收到該操作指令後,就立即將本段資料傳送出去,而不必等待傳送緩衝區滿;二是對於接收方引起的粘包,則可通過優化程式設計、精簡接收程序工作量、提高接收程序優先順序等措施,使其及時接收資料,從而盡量避免出現粘包現象;三是由接收方控制,將一包資料按結構字段,人為控制分多次接收,然後合併,通過這種手段來避免粘包。
以上提到的三種措施,都有其不足之處。第一種程式設計設定方法雖然可以避免傳送方引起的粘包,但它關閉了優化演算法,降低了網路傳送效率,影響應用程式的效能,一般不建議使用。第二種方法只能減少出現粘包的可能性,但並不能完全避免粘包,當傳送頻率較高時,或由於網路突發可能使某個時間段資料報到達接收方較快,接收方還是有可能來不及接收,從而導致粘包。第三種方法雖然避免了粘包,但應用程式的效率較低,對實時應用的場合不適合。
一種比較周全的對策是:接收方建立一預處理執行緒,對接收到的資料報進行預處理,將粘連的包分開。對這種方法我們進行了實驗,證明是高效可行的。
三、程式設計與實現
1.實現框架
實驗網路通訊程式採用tcp/ip協議的socket api程式設計實現。socket是面向客戶機/伺服器模型的。tcp實現框架如圖4所示。
圖42.實驗硬體環境:
伺服器:pentium 350 微機
客戶機:pentium 166微機
網路平台:由10兆共享式hub連線而成的區域網
3.實驗軟體環境:
作業系統:windows 98
程式語言:visual c++ 5.0
4.主要執行緒
程式設計採用多執行緒方式,伺服器端共有兩個執行緒:傳送資料執行緒、傳送統計顯示執行緒。客戶端共有三個執行緒:接收資料執行緒、接收預處理粘包執行緒、接收統計顯示執行緒。其中,傳送和接收執行緒優先順序設為thread_priority_time_critical(最高優先順序),預處理執行緒優先順序為thread_priority_above_normal(高於普通優先順序),顯示執行緒優先順序為thread_priority_normal(普通優先順序)。
實驗傳送資料的資料結構如圖5所示:
圖55.分包演算法
針對三種不同的粘包現象,分包演算法分別採取了相應的解決辦法。其基本思路是首先將待處理的接收資料流(長度設為m)強行轉換成預定的結構資料形式,並從中取出結構資料長度字段,即圖5中的n,而後根據n計算得到第一包資料長度。
1)若n3)若n>m,則表明資料流內容尚不夠構成一完整結構資料,需留待與下一包資料合併後再行處理。
對分包演算法具體內容及軟體實現有興趣者,可與作者聯絡。
四、實驗結果分析
實驗結果如下:
1.在上述實驗環境下,當傳送方連續傳送的若干包資料長度之和小於1500b時,常會出現粘包現象,接收方經預處理執行緒處理後能正確解開粘在一起的包。若程式中設定了「傳送不延遲」:(setsockopt (socket_name,ipproto_tcp,tcp_nodelay,(char *) &on,sizeof on) ,其中on=1),則不存在粘包現象。
2.當傳送資料為每包1kb~2kb的不定長資料時,若傳送間隔時間小於10ms,偶爾會出現粘包,接收方經預處理執行緒處理後能正確解開粘在一起的包。
3.為測定處理粘包的時間,傳送方依次迴圈傳送長度為1.5kb、1.9kb、1.2kb、1.6kb、1.0kb資料,共計1000包。為製造粘包現象,接收執行緒每次接收前都等待10ms,接收緩衝區設為5000b,結果接收方收到526包資料,其中長度為5000b的有175包。經預處理執行緒處理可得到1000包正確資料,粘包處理總時間小於1ms。
實驗結果表明,tcp粘包現象確實存在,但可通過接收方的預處理予以解決,而且處理時間非常短(實驗中1000包資料總共處理時間不到1ms),幾乎不影響應用程式的正常工作。
解決TCP網路傳輸「粘包」問題
解決tcp網路傳輸 粘包 問題http www.ciw.com.cn 當前在網路傳輸應用中,廣泛採用的是tcp ip通訊協議及其標準的socket應用開發程式設計介面 api tcp ip傳輸層有兩個並列的協議 tcp和udp。其中tcp transport control protocol,傳輸控...
解決TCP網路傳輸 粘包 問題
文章出處 http blog.csdn.net michelsn archive 2008 01 02 2009894.aspx 當前在網路傳輸應用中,廣泛採用的是tcp ip通訊協議及其標準的socket應用開發程式設計介面 api tcp ip傳輸層有兩個並列的協議 tcp和udp。其中tcp ...
解決TCP網路傳輸「粘包」問題
解決tcp網路傳輸 粘包 問題 當前在網路傳輸應用中,廣泛採用的是tcp ip通訊協議及其標準的socket應用開發程式設計介面 api tcp ip傳輸層有兩個並列的協議 tcp和udp。其中tcp transport control protocol,傳輸控制協議 是面向連線的,提供高可靠性服務...