應用層通信協議開發淺析


Original:http://blog.csdn.net/phunxm/article/details/5086080

1.通信協議的概念及其要素

在OSI開放互聯參考模型中,對等實體(peer)之間數據單元在發送方逐層封裝(encapsulation),在接收方的逐層解析(decapsulation)。發送方N層實體從N+1層實體得到的數據包稱為服務數據單元(Service Data Unit,SDU)。N層實體只將其視為需要本實體提供服務的數據,將服務數據單元進行封裝,使其成為一個對方能夠理解的數據單元(Protocol Data Unit,PDU),封裝過程實際上是為SDU增加對等實體間約定控制信息(Protocol Control Information,PCI)的過程。

為了保證網絡的各個功能的相對獨立性,以及便於實現和維護,通常將協議划分為多個子協議,並且讓這些協議保持一種層次結構,子協議的集合通常稱為協議簇(Protocol Family)。

網絡協議的分層有利於將復雜的問題分解成多個簡單的問題,從而分而治之。各層的協議由各層的實體(entity)實現,通信雙方對等層中完成相同協議功能的實體稱為對等實體。對等實體按協議進行通信,所以協議反映的是對等層的對等實體之間的一種橫向關系,嚴格地說,協議是對等實體共同遵守的規則和約定的集合。

通信協議精確地定義了雙方通信控制信息和解釋信息:發送方能將特定信息(文本、圖片、音頻、視頻)按協議封裝成指定格式的數據包,最終以串行化比特流在網絡上傳輸;接收方接收到數據包后,根據協議將比特流解析為本地化數據,從而獲取對方發送過來的原始信息。

通信協議包括三個要素:

(1)語法:規定了信息的結構和格式;

(2)語義:表明信息要表達的內容;

(3)同步:規則涉及雙方的交互關系和事件順序。

整個計算機網絡的實現體現為協議的實現,TCP/IP協議是Internet互聯網的核心協議。

 

2.通信協議開發步驟

(1) 協議的開發主要包括協議設計、協議形式描述、協議實現和協議一致性測試。協議的開發過程與步驟如圖1所示。

 

圖1 協議開發過程與步驟

(2) 協議設計過程中的分組發送接收模型如圖2所示。

 

 

 

圖2協議設計過程中的分組發送接收模型

(3)協議的一致性測試

協議的一致性測試是指測試協議能否按照預想的控制策略實現正確的通信,主要體現在數據包通過信道從信源傳送到信宿后,信宿能夠根據協議正確的解析出原始信息。

協議的一致性測試如圖3所示。

 

圖3 協議一致性測試環境

根據測試環境的可以分為局部測試和分布式測試,如圖4所示。

 

圖4局部測試法、分布式測試法

 

3.數據包和數據報

為方便描述自定義協議,還是借用數據包和數據報來描述封裝數據單元和傳輸數據單元,但這里的數據包和數據報完全不同於TCP/IP架構中的Packet和Datagram概念。

下文所述的數據包指封裝的基本單位,以TLV(Type-Length-Value)格式封裝基本消息單位;數據報Package是傳輸的基本單位,頭部包含序列號和命令信息。接收端根據命令信息分辨事件類型,做出不同的解析。報文實體是多個TLV數據包組成的鏈表


4.數據包TLV的設計

從應用層HTTP協議,到超文本置標語言HTML(HyperText Mark-up Language),再到可擴展置標語言XML(Extensible Markup Language),它們提供了數據的格式化存儲、傳輸和格式化顯示的規范,是網絡通信的基石。然而HTTP協議以及HTML/XML置標語言的本質就是定義一堆標簽(Tag)對數據進行串行化序列化,然后接收方再根據標簽解析、還原數據。

自定義通信協議的關鍵是對數據包的合理構造(construct)和正確解析(parse),即制定編解碼規則

抽象語法標記ASN(Abstract Syntax Notation) BER的長度確定的編碼方式,由3部分組成Identifier octets、Length octets和Contents octets,實際上這就是一種TLV(Type-Length-Value)模型:類型字段(Type或Tag)是關於標簽和編碼格式的信息;長度字段(Length)定義數值的長度; 內容字段(Value)表示實際的數值。

因此,一個編碼值又稱TLV三元組。編碼可以是基本型或結構型,如果它表示一個簡單類型的、完整的顯式值,那么編碼就是基本型(primitive);如果它表示的值具有嵌套結構,那么編碼就是結構型 (constructed)。

TLV編碼就是指對Type(Tag)、Length和Value進行編碼,形成比特流;解碼是編碼的過程,是從比特流緩沖區中解析還原出原始數據。

采用C++編程語言設計TLV協議類,其類視圖如圖5所示。

 

圖5 CTLV類視圖

目前只提供設置整形值(int型)的setValue_Int和設置字符串值(C_String型)的SetValue_Cstring兩個接口。

TLV將數據封裝成包的格式如表1所示。 

 

 

TLV包

頭部

包實體

m_dwTag

m_nLen

m_pValue

 

 表1 TLV包格式

TLV的接口說明:

(1)值類型標簽m_vtTag是內部輔助枚舉變量,它根據構造TLV時傳遞的服務類型標簽m_dwTag來確定。

(2)TLV::m_nLen在為TLV設置具體值時確定。

(3)TLV包的封裝:

 

  •  使用Tag參數創建一個TLV對象后,調用TLV::setValue_*方法為TLV填充具體值;
  •  調用TLV::toBuffer方法打包到緩沖區streamBuffer。

 

(4)TLV包的解析:創建一個TLV對象后,調用TLV::fromBuffer方法從緩沖區streamBuffer解析出TLV。

(5)封裝和解析涉及到本機字節順序和網絡字節順序的轉換問題。

(6)調用TLV::setValue_*方法填充TLV時,統一字節邊界數為4。

 

5.數據報Package的設計

不同於底層的數據包/數據報只是對數據層次的封裝解析,實際應用程序是以事件驅動的,因此必須注冊不同的信令(事件類型標簽),然后填充到數據報中。接收端根據信令做出相應的事件處理。

例如在C/S通信系統中,客戶端往往要先登錄,通過服務器端的校驗才能進行后續通信。因此客戶端運行后,需要構造並向服務器端發送含有LOGIN信令的包含用戶名字符串strUserName和密碼字符串strPassWord的數據報;服務器端解析LOGIN信令后做校驗處理,然后發送含有LOGIN_RESPONSE信令和校驗結果的回執數據報給客戶端。

采用C++編程語言設計Package類,其類視圖如圖6所示。

 

 

圖6 CPackage類視圖

Package類將TLV封裝成包的格式如表2所示。

 

Package包

頭部

序列號

包實體

m_nCmdLen

m_dwCmdID

m_dwCmdState

m_nSeqNo

Count*TLV

 

 

表2 Package包格式

Package的接口說明:

(1)Package::m_nCmdLen是整個Package包的長度,將其作為首個字段的好處在於當傳送大數據包時,接收方可以根據數據長度來控制讀狀態,從而將一個大數據包分批接收。

(2)Package::m_nCmdLen在構造函數中初始化為16,在調用Package::addTLV方法填充包實體時增長。

(3)Package包的封裝:

 

  • 創建Package對象后,調用Package::setHeader方法填充頭部信令;
  • 創建TLV對象並填充數據,再調用Package::addTLV方法填充包實體;
  • 調用Package::toBuffer方法將Package打包到緩沖區streamBuffer。

 

(4)Package包的解析:

 

  • 先創建一個Package對象,調用Package::fromBuffer方法從緩沖區streamBuffer先解析出Package的頭部和序列號,再從剩余緩沖區中解析出TLV並將其串行化到鏈表。
  • 調用Package::getTLV方法根據Tag從鏈表中查找具體TLV包,再調用TLV::getValue方法取得具體值。

 

(5)Package::toBuffer方法和Package::fromBuffer方法主要遍歷Package::m_TLV_List列表,然后調用TLV::toBuffer方法和TLV::fromBuffer方法解析出TLV數據單元。

TLV數據包的功能測試(主要是本地測試)

鑒於實際通信數據最后都要轉換成比特流,故只測試發送字符串類型的變量,僅測試協議能否正確打包、解析。其他類型的普通數據都可以轉換成字符串傳輸,最后,接收方根據m_dwTag確定值類型m_vtTag,解析出具體值。

對TLV::setValue_C_String方法填充TLV的測試,需要考慮字節對齊問題。對於長度為4字節倍數的C狀態字符串,打包時省去末尾的‘/0’結束標志符。需要測試長度非4倍數的字符串和長度為4倍數的字符串。

經本地測試,調用TLV::setValue_Int方法和TLV::setValue_C_String方法構造整形和字符串時,能夠正確封裝、正確解析。

Package數據報的功能測試,主要是將TLV組合成包,然后添加信令,完成特定的通信。對登陸LOGIN和發送消息SUBMIT_SM的測試表明Package協議能正確封裝、正確解析。

在實際項目中使用Package通信協議,對於稍大一點的數據塊需要控制好讀的步驟,以便能接收整包完整的信息。


本文示例代碼下載:《TLV應用層協議開發示例

 

參考:

《計算機網絡協議和實現技術》 魯士文

TLV 格式及編解碼示例

XML和TLV打包解包性能比較

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM