漫談應用協議資料分包

2021-06-07 04:36:35 字數 1839 閱讀 8936

範圍:本文就基於流式協議(以tcp為例)設計應用信令協議時,考慮什麼時候需要分包,怎樣確定分包大小,如何保證業務信令的順序等方面展開討論。

基礎:我們應該知道,實現基於流式協議的應用層協議的第一步,是定義用於把資料流組解成完整包(訊息或信令)的訊息邊界

,通過轉義保證信令資訊的完整性,並防止「粘包」。訊息邊界包含的資料即是本文討論的應用協議的資料報。

一、應用協議需要分包嗎?

我們知道,tcp傳輸層協議底層對 資料分組包、路由、流量控制等已進行了處理,按理說,應用層只需要呼叫send/recv函式進行資料傳輸即可,我們還需要對應用資料進行分包呢?

對大多數的應用場景答案是需要!理由有二:

第一,大多數情況下,進行通訊的傳送方和接收方在呼叫socket api的 send\recv時,對對方需要通過api傳送的資料大小難以**或說是一無所知。資料接收方例程呼叫recv的快取區大小一般不會無限大的(當然也非強制限制啦:d) , 若在應用層協議約定了每次資料分包的範圍,則可以預先確定接收緩衝區的大小,這對更合理地設計應用層是有利的。

第二,主要從通訊效率角度考慮。網路環境較複雜,應用層資料很多時候(考慮路由重啟、斷線重連、超時等情況)需重發。考慮應用傳輸1g的檔案資料,若僅僅呼叫一次send函式理論上也是可行的,但每次重發時需冒著最大可能重發接近1g資料的風險,這無論是從網路利用率還是從信令響應時間上考慮,都是不能容忍的;若考慮tcp底層ip包最大[64kb/包]及tcp視窗大小限制,我們可以把應用協議資料報定義在[16kb~32kb/包]之間,這樣可以最大程度減少重發的巨量浪費(但也有代價,我們需要付出更多ip報頭及組解包計算等開銷)。以上沒考慮資源限制,如系統對物理頁面鎖定限制以及系統預設快取對通訊效率的影響。

當然,對於一些應用信令協議大小範圍確定且控制在[ 64kb/包 ]以內的應用場景,可不考慮協議資料分包。

二、如何確定分包大小呢?

其實在第一點就可以找到答案:既要考慮應用信令協議資料大小的範圍,又要兼顧ip包[ 64kb/包 ]的限制。

例如,應用系統絕大多數信令協議資料報在8kb以內,只有少數、不頻發的信令資料超出該範圍,此時定義分包大小為[8kb/包]應該是個合理的選擇。

三、是否需要制定業務信令的順序號呢?

考慮以下情況:傳送方在1s內向接收方傳送2000次同乙個業務請求信令(這在一些實時資料採集的應用場合較常見),假定傳送方對信令資料處理有順序性要求而非同步處理業務後的響應可能是隨機的,此時從效率上考慮不採用時間戳比較的方式,如何保證接收方回應傳送方的請求響應信令是順序的呢?換句話說,傳送方收到接收方應答時如何確定哪次應答是自己在哪次發的請求呢?

考慮大多數通訊實現為非同步的事實,該類情況下,通過制定業務信令順序號,要麼解包時計入順序號,要麼在業務層驗證該序號,均可以達到順序處理業務的目的。

四、注意區分分包順序與業務信令順序號:

包順序是由應用通訊層定義分包控制欄位來保證的,分包控制字段應該包含是否已分包及分包結束標識等資訊。傳送例程順序呼叫send來保證outgoing資料報的順序,接收例程根據分包控制字段確定如何組包並最終還原完整的應用信令協議資料報。

業務信令順序號需要業務層還是協議層定義?

可以在解包後的完整信令資料投遞到上層應用之前(協議層)依據順序號決定投遞順序,也可以把該項任務交由上一層應用(業務層)自行處理。個人傾向於前者。

同一信令的不同分包應屬於同一業務順序號的業務信令。

IOCP 二進位制協議 分包

一 iocp 二進位制協議分包的思路 解析資料頭,獲取協議包體的大小,判斷是否收到乙個完整的資料頭,如果不是,繼續投遞recv請求,直到收到乙個資料頭 異常的資料報,關閉session pkg size max pkg size 全部資料收到,進行處理.1 判斷long pkg是否存在,如果存在,就...

TCP協議中的粘包分包問題

使用tcp協議進行網路遊戲開發的時候,有粘包和分包兩個問題。粘包和分包是利用socket在tcp協議下內部的優化機制,在使用tcp協議進行資料的傳輸進行通訊的時候,會出現粘包分包問題的話,是由於優化導致,即內部的資料傳輸機制所導致的。在客戶端呼叫send 方法傳送資料,每傳送的資料稱為包 當傳送資料...

android中資料的分包

之前在開發中,遇到了乙個問題,就是在專案assets下有乙個apk需要在應用啟動時安裝到裝置中,實現的思路是需要首先將apk拷貝到sdcard中,然後執行安裝操作,還有乙個問題就是專案中的資料庫也需要放在sdcard中,這個apk大約有5m左右,我的資料庫大約有30m左右,接下來我就按照普通的i o...