不論使用二進位制訊息格式還是文字訊息格式例如xml訊息,訊息分發框架都是建立在固定的訊息頭內容的基礎之上的,因為只要解析出訊息頭就完全可以進行訊息分發了。一般來說,訊息頭至少包含以下內容:訊息型別、訊息id、訊息序列號。為了滿足將來業務功能的擴充套件需要(比如可令伺服器作為乙個訊息**中心,將某些前台客戶端發來的業務訊息**給另外一些後台客戶端,後台客戶端作為業務伺服器,訊息**伺服器又可稱為**伺服器),有必要為訊息頭增加源客戶端id和目的客戶端id。
2.3.1 訊息頭結構
因此,我們將訊息頭對應的結構定義為:
class messageheader
;typedef smartptrmessageheadersmartptr;
客戶端id和訊息序列號都為整數,具體型別及其分配或獲取方法應由應用層的業務邏輯按需要而定。訊息型別和訊息id可以使用整數值或者字串常量來表示,當然得根據使用者選擇使用文字訊息格式還是二進位制訊息格式而定。
為了適應使用者的需要,該框架支援xml業務訊息格式和二進位制業務訊息格式,並用乙個預定義巨集來配置,使用者可以在這兩種訊息格式之間靜態切換,或者增加第三種訊息格式,但是乙個系統中只能使用其中一種格式:
#if 1
#ifndef _use_xml_message_format_
#define _use_xml_message_format_
#endif
#else // 0
#ifndef _use_binary_message_format_
#define _use_binary_message_format_
#endif
#endif // 1
因為本框架同時支援兩種業務訊息格式,所以後續的實現將依賴於這兩個巨集定義。由於二進位制訊息格式存在多位元組資料字節序轉換的問題,比較繁瑣,所以本框架預設採用xml訊息格式。如果使用者想支援二進位制訊息格式,只需切換上述巨集定義後重新編譯客戶端和伺服器端的框架層即可。具體請參見標頭檔案hyq_framework_config.h。
本框架支援的訊息型別、部分訊息id以及基本資料型別定義如下:
#ifdef _use_xml_message_format_
// 訊息型別取值範圍
const char * const _unknown_message_type_ = "";
const char * const message_type_request = "request"; // 請求訊息
const char * const message_type_ack = "ack"; // 應答訊息
const char * const message_type_notify = "notify"; // 通知訊息
// 要求**伺服器從乙個客戶端廣播到其他客戶端
const char * const message_type_broadcast = "broadcast";// 廣播訊息
const char * const message_type_local = "local"; // 本地產生的訊息
typedef std::string messagetype; // 訊息型別
typedef std::string servicelayermessage; // 訊息的資料型別
// 公共訊息id
const char * const _unknown_message_id_ = "";
const char * const local_message_linkdown = "linkdown";
const char * const local_message_linkup = "linkup";
const char * const local_message_timer1second = "timer1second";
// 使用者在這裡新增自定義業務訊息id
const char * const service_message_x = "***x";
const char * const service_message_a = "aaaa";
……typedef std::string messageid; // 字串常量作為訊息id
#elif defined(_use_binary_message_format_)
// 訊息型別取值範圍
enum _enum_messagetypecode
;typedef _enum_messagetypecode messagetype; // 訊息型別
typedef std::vectorservicelayermessage; // 訊息的資料型別
enum _enum_messageid
;typedef _enum_messageid messageid; // 整數作為訊息id
#endif
typedef ushort serialnumber; // 訊息序列號型別
typedef int clientid; // 客戶端id型別
typedef std::listclientidlist; // 客戶端id列表型別
typedef smartptrclientidlistsmartptr;
另外還有一些基本的常量定義如下:
enum
;enum
;**伺服器的id固定設定為0。如果客戶端a的某個訊息是傳送給另乙個客戶端b的,那麼訊息頭中的目標客戶端id就應該設定為b的id(當然,首先是傳送給**伺服器,然後再由**伺服器**);相反如果訊息就是傳送給**伺服器的,那麼訊息頭中的目標客戶端id就應該設定為0。任何客戶端的id,不論是靜態分配好的還是由**伺服器動態分配的,都不應為0。
2.3.2 xml訊息和二進位制訊息的格式框架
確定了訊息頭的內容後,我們就可以定義xml業務訊息的格式如下:
訊息型別:request|ack|notify|broadcast|local
源客戶端id或者-1
目的客戶端id或者0
訊息序列號
訊息id
業務訊息的訊息體內容,由使用者自己定義
定義二進位制訊息的格式如下圖所示:
圖2-3 二進位制業務訊息格式
分別對應的半結構化訊息型別定義如下:
struct xmlhalfstructuredmessage
;#ifdef _use_xml_message_format_
typedef smartptrhalfstructuredmessagesmartptr;
#endif // _use_xml_message_format_
typedef std::vectorbinmessagebody;
struct binhalfstructuredmessage
;#ifdef _use_binary_message_format_
typedef smartptrhalfstructuredmessagesmartptr;
#endif // _use_binary_message_format_
顯然,在乙個系統中只能選擇其中之一。
xmlmessagebody是對domdocument的乙個封裝,具體實現請參考附錄指出的**(hyq_xml_message_body.h)。
當需要在客戶端之間傳遞訊息時,以**伺服器作為**中心並配合這樣的訊息格式設計,就可以大大簡化它們之間的連線關係,也可以簡化為完成訊息傳送所需做的工作。啟用訊息**的前提是必須同時在客戶端和**伺服器上啟用系統路由表功能,以及實現路由同步機制。關於路由表實現,請參考本章2.9節。
基於訊息驅動的物件導向通用C S應用框架 九
有了訊息格式作為基礎,就可以實現半結構化訊息解析器和介面networkobserver了。通訊層和框架之間的networkobserver介面顯然是使用了observer設計模式。我們先來看它的實現類定義 class networkobserverimpl public networkobserve...
C S 物件導向的程式設計概念理解
物件導向的程式設計 物件導向的程式設計 為了能更加直接地描述客觀世界中存在的事務以及它們之間的關係。是不是難以理解。這個困難的東西先掛會,一會解答。何為物件?物件 客觀現實世界在人腦中的反映,作為一種概念而存在,通俗點舉個例子,就是現實世界真實存在的事務,有形的如乙個人,無形的如乙份計畫。所有的事物...
物件導向和基於物件的區別
很多人沒有區分 物件導向 和 基於物件 兩個不同的概念。物件導向的三大特點 封裝,繼承,多型 卻一不可。通常 基於物件 是使用物件,但是無法利用 現有的物件模板產生新的物件型別,繼而產生新的物件,也就是說 基於物件 沒有繼承的特點。而 多型 表示為父類型別的子類物件例項,沒有了繼承的概念也 就無從談...