龐銳 呂達 陳科
摘要: 針對現(xiàn)代軟件系統(tǒng)中模塊協(xié)同工作的通信需求,提出了一個軟件通信框架的完整實現(xiàn)方案。通過分析軟件系統(tǒng)中對模塊通信的要求,建立統(tǒng)一的事件模型,完成進程間、進程內通信框架設計,并利用Qt開發(fā)庫完成通信框架的軟件實現(xiàn)。使用該軟件通信框架可以減少模塊通信復雜度,縮短軟件通信功能開發(fā)周期,提高軟件可維護性,而且利于擴展和移植。
關鍵詞: 模塊通信; 事件模型; 軟件框架; 面向對象; Qt
中圖分類號:TP391文獻標志碼:A 文章編號:1006-8228(2012)11-16-03
Design and implementation of software communication framework based on uniform event model
Pang Rui, Lv Da, Chen Ke
(SINOPEC Geophysical Research Institute, Nanjing, Jiangsu 211103, China)
Abstract: Targeted on module communication requirement of modern software system, a solution to software communication framework is proposed. By analyzing communication requirement in module development, uniform event model is constructed, and software framework for module communication is designed. Finally, by using Qt, a communication framework is realized. Using the framework can reduce module complicacy and shorten development period of communication. Furthermore, software maintenance is improved, and software transplant benefits.
Key words: module communication; event model; software framework; object-oriented; Qt
0 引言
隨著計算機技術的飛速發(fā)展,各類軟件系統(tǒng)為了滿足不斷變化的用戶需求,提供的功能越來越多,其軟件規(guī)模日益龐大,實現(xiàn)復雜度也越來越高。在現(xiàn)代軟件系統(tǒng)中,對復雜的業(yè)務需要進行層次劃分,將業(yè)務功能相對模塊化,模塊具備高內聚低耦合的特性,通過模塊間的協(xié)同工作來提供復雜的軟件功能[1]。軟件模塊協(xié)同工作的基礎是在模塊間可以傳遞信息數(shù)據(jù),根據(jù)業(yè)務劃分不同,可以在一個進程中只包含一個模塊,通過進程間模塊通信協(xié)同工作,也可以在一個進程中包含多個模塊,通過進程內模塊通信協(xié)同工作。那么,建立一個高效統(tǒng)一的進程間、進程內事件通信機制,才能保證各個模塊間可靠的協(xié)作關系,降低軟件系統(tǒng)通信復雜度,提高開發(fā)效率。
1 軟件模塊的通信需求分析
面向不同的行業(yè)應用領域,軟件模塊的通信需求是不同的。在專家決策系統(tǒng)中,模塊間需要借助通信對同一數(shù)據(jù)進行聯(lián)動操作分析;在游戲軟件中,模塊間需要利用通信對用戶交互操作進行協(xié)同處理;在計費軟件中,模塊間需要傳遞各種費用數(shù)據(jù)。各類軟件系統(tǒng),其共同點是,需要在模塊間傳遞特定的事件通知或數(shù)據(jù)信息,以協(xié)同完成工作。根據(jù)不同軟件系統(tǒng)的設計,軟件模塊的通信可以分類為進程間通信和進程內通信。
⑴ 進程間通信
軟件模塊分散在不同的進程中,模塊需要通過進程間的通信手段來傳遞事件通知和數(shù)據(jù)信息。通常操作系統(tǒng)提供的進程間通信(IPC)方式主要有:信號、信號量、消息隊列、管道、共享內存、套接字等。其中,信號、信號量、消息隊列可以用于傳遞事件通知,管道、共享內存可以用于傳遞數(shù)據(jù)信息,套接字的應用更為靈活,可以同時用于事件和數(shù)據(jù)的傳遞[2]。此外,在Windows操作系統(tǒng)中,還可以利用窗口消息來傳遞事件。雖然操作系統(tǒng)提供了多種進程間通信手段,但是大都與操作系統(tǒng)底層接口緊密相關,如果直接使用,在兼容性和跨平臺方面有所不足。
⑵ 進程內通信
軟件模塊集中在一個進程中,模塊通過進程內的通信手段來傳遞事件通知和數(shù)據(jù)信息。有別于進程間通信中各個模塊受進程空間隔離,在同一進程內的模塊可以共享進程的內存數(shù)據(jù),可以相互調用模塊接口。因此,進程內通信方式比較靈活,可以引用模塊的指針來訪問模塊,也可以向模塊發(fā)消息??紤]到軟件開發(fā)的規(guī)范,需要對進程內通信形式進行統(tǒng)一約定。
2 軟件通信框架設計
2.1 統(tǒng)一的事件模型設計
軟件通信的主要任務就是在模塊間傳遞數(shù)據(jù)。其首要問題是如何對要傳遞的數(shù)據(jù)進行規(guī)范描述,我們必須建立一個適用于進程內,同時也適用于進程間傳遞的統(tǒng)一事件模型。這個事件模型并不是具體傳遞的事件數(shù)據(jù),它是一個規(guī)范標準,一個模板,所有參與通信的模塊必須圍繞這個事件模型,定義自己需要接收或發(fā)送的具體事件,最終模塊間傳遞的是這些已定義的事件,雖然它們代表的信息各不相同,但都是基于同一個事件模型,有著相同的規(guī)范描述。圖1描述了進程間和進程內事件傳遞的模型結構。
圖1事件模型結構圖
一個事件模型需要包含如下基本信息。
事件標識ID:一個整數(shù),表明這個事件的含義;
發(fā)送模塊標識ID:一個整數(shù),標識是從哪個模塊發(fā)送的事件;
接受模塊標識ID:一個整數(shù),標識事件應由哪個模塊接收;
事件攜帶的信息:一個有限長度的數(shù)據(jù)緩沖,可以攜帶和事件標識ID相關的附加信息。
軟件模塊開發(fā)人員以事件模型為基礎,定義模塊間需要傳遞的具體事件,每個事件包括特定的事件標識。
ID:需要攜帶的信息及信息在數(shù)據(jù)緩沖中的存放方式。當需要發(fā)送事件時,構造一個事件對象,設置發(fā)送模塊ID和接收模塊ID,再利用通信框架提供的發(fā)送接口把事件發(fā)送出去,由通信框架將事件傳遞到接收模塊中。
2.2 基于事件模型的通信框架設計
事件模型是對要傳遞數(shù)據(jù)的規(guī)范描述,那么使用什么載體和機制來傳遞事件則是軟件通信的另一個重要部分。圍繞事件模型,我們需要建立軟件通信框架,為事件在模塊間的傳遞提供基礎支撐。軟件通信框架是一組通用組件以及使用規(guī)約的集合,它定義了最基本的事件傳遞流程,并提供相關調用接口,軟件模塊要依據(jù)通信框架的使用規(guī)約,進行具體的事件發(fā)送和接收工作。按照事件傳遞的途徑不同,可以分為進程間通信和進程內通信兩種框架,它們之間有相通之處,但是在事件載體方面有所區(qū)別。
⑴ 進程間通信框架
當各個模塊存在于獨立的進程中時,需要在進程間傳遞事件。進程間通信框架采用服務器/客戶端模式:首先存在一個通信服務進程,各個模塊進程啟動后,向通信服務進程注冊自己;然后,各個模塊進程向通信服務進程發(fā)送自己的事件,由通信服務根據(jù)事件的接收者再把事件轉發(fā)到對應的接收模塊上;最后,當模塊進程退出時,要向通信服務注銷自己。進程間通信框架結構如圖2所示。
[通信組件][通信服務進程] [通信組件] [通信組件][發(fā)送事件模塊(進程A)][接收事件模塊(進程B)] [event] [操作系統(tǒng)
底層載體][event]
圖2進程間通信框架結構圖
此外,考慮到通信框架的通用性,設計了通用的進程間通信組件。模塊進程和服務進程都通過通信組件來傳遞事件,由通信組件選擇合適的操作系統(tǒng)的底層功能作為事件的載體,進行傳送,這樣可以在通信框架層次上隱藏底層細節(jié)。
⑵ 進程內通信框架
當各個模塊存在于同一個進程中時,需要在進程內傳遞事件。進程內通信框架和進程間框架類似,也是采用服務/客戶端模式,其特別之處是服務端和客戶端都在一個進程內部。同時,利用進程內可以共享數(shù)據(jù)的特點,省略了通信組件這個層次,各個模塊直接向通信服務對象注冊自己,并直接向通信服務對象發(fā)送事件,再由其將事件轉發(fā)到相關接收模塊。這樣既保持了進程間和進程內通信框架的結構統(tǒng)一性,又提高了進程內的通信效率。進程內通信框架結構如圖3所示。
[通信服務對象(進程內)][發(fā)送事件模塊(進程內)][接收事件模塊(進程內)][event][event]
圖3進程內通信框架結構圖
3 軟件通信框架實現(xiàn)
基于上述軟件通信框架的設計,使用面向對象的開發(fā)方法(C++編程語言),在Qt開發(fā)庫的基礎上進行軟件通信框架的開發(fā)實現(xiàn)。面向對象開發(fā)方法以對象為基礎,利用特定的軟件工具直接完成從對象客體的描述到軟件結構之間的轉換,解決了傳統(tǒng)結構化開發(fā)方法中客觀世界描述工具與軟件結構的不一致性問題,縮短了開發(fā)周期,解決了從分析和設計到軟件模塊結構之間多次轉換映射的繁雜過程,是一種很有發(fā)展前途的系統(tǒng)開發(fā)方法[3]。Qt是一個先進的,面向對象的,跨平臺的圖形開發(fā)庫,其主要優(yōu)點是: 優(yōu)良的跨平臺特性,支持Windows、Linux操作系統(tǒng);面向對象特性,良好封裝機制使得Qt的模塊化程度非常高,可重用性較好,對于用戶開發(fā)來說是非常方便的;豐富的API,包括多達250個以上的具有強大功能的C++類[4]。
3.1 事件模型實現(xiàn)
Qt本身包含一套事件模型,我們根據(jù)自己事件模型的設計,在Qt事件的基礎上,利用面向對象的派生特性[5],進行擴展,形成事件模型NewsEvent,整個通信框架都使用NewsEvent進行通信,主要實現(xiàn)代碼如下:
#define NEInvalid -1 //無效事件ID
//模塊的identify_key,也作為_senderId or_recverId:
#define NewsMain_ID0
#define Area_ID 1
#define Seis_ID2
class NewsEvent:public QEvent //在QEvent基礎上進行擴展
{//下邊是進程間需要傳遞的核心數(shù)據(jù),一共132個字節(jié)
(32位系統(tǒng))
long_senderId; //發(fā)送模塊的identify_key
int_recverId; //接收模塊的identify_key,發(fā)給所有帶這個識別
key的模塊
int_eventId; //事件ID:普通事件ID必須>0,<=0的事件ID用作
特殊系統(tǒng)管理
union EventData//事件攜帶的信息,可以根據(jù)事件id約定如何
使用其中的相關數(shù)據(jù)項
{char charValue[120];
short shortValue[60];
int intValue[30];
float floatValue[30];
double doubleValue[15];
}_eventData;
};
在事件ID的定義方面,提供了統(tǒng)一的事件ID定義函數(shù),可以對不同模塊的事件ID進行管理,避免不同模塊間事件ID的沖突。
//NEMAKER是事件ID生成器:用模塊標志頭組合內部ID,
生成惟一的事件ID
#define NEMAKER(frame,id) NEMAKER_p(frame,id)
#define NEMAKER_p(frame,id) frame##id
/****各類模塊事件標志頭****/
#define NENewsMain 10
#define NEArea 11
#define NESeis 12
//###系統(tǒng)管理###
#define NEClientRegister -998 //client向通信服務進程注冊自己
#define NEClientUnregister -999 //client向通信服務進程注銷自己
//###剖面模塊###
#define NEMousePositionInSection NEMAKER(NESeis,0)
//鼠標在剖面上的位置
#define NEInterpretDataChangeInSection NEMAKER(NESeis,1)
//剖面上解釋數(shù)據(jù)變動
各個模塊根據(jù)自己的需求,定義自己的事件ID,并約定好事件所攜帶的信息,以NewsEvent對象的形式通過框架接口將事件發(fā)送出去,接收時,通過框架接口接收NewsEvent對象,并進行處理。
3.2 通信框架實現(xiàn)
基于Qt的事件傳遞機制,開發(fā)軟件通信框架。因為Qt提供了完善的對象間(同一進程內)傳遞事件的機制,通信框架可以把軟件模塊作為對象,利用Qt進行事件傳遞。我們的主要工作是實現(xiàn)發(fā)送/接收事件的標準接口,進程間通信組件,進程間通信服務程序及進程內通信服務對象。
⑴ 發(fā)送/接收事件標準接口
void SendNewsEvent(QObject* target,NewsEvent* event); //發(fā)送事件
virtual void ProcessNewsEvent(NewsEvent* event); //接收事件
所有需要發(fā)送事件的模塊都使用SendNewsEvent發(fā)送事件,所有需要接收事件的模塊都重新實現(xiàn)ProcessNewsEvent虛函數(shù),進行事件處理。在進程間通信中,SendNewsEvent函數(shù)中的target是模塊自己的通信組件,由通信組件將事件發(fā)送給通信服務程序。在進程內通信中,target是進程內惟一的通信服務對象。
⑵ 進程間通信組件
進程間通信組件用于進程間通信框架,它是模塊與通信服務程序的連接橋梁,模塊通過通信組件向通信服務程序注冊自己,發(fā)送事件,接收事件,通信服務程序通過通信組件向模塊轉發(fā)事件。考慮到跨平臺的兼容性,通信組件使用套接字(Socket)作為事件的載體,在模塊和通信服務程序間傳遞數(shù)據(jù)。
在進程間通信中,模塊并不是直接將NewsEvent發(fā)送給通信服務程序,而是發(fā)送給進程間通信組件,由其將事件發(fā)送到通信服務程序,同樣,通信服務程序發(fā)來的事件也是由通信組件接收,再發(fā)送給目標模塊。
void ClientRegister(); //模塊調用其向通信服務程序進行注冊
void ClientUnregister(); //模塊調用其向通信服務程序進行注銷
void TransNewsEvent(NewsEvent* event,QHostAddress &ip,
quint16 port); //發(fā)送事件到服務程序
void ReceiveNewsEvent(NewsEvent* event); //從服務程序接收事件
⑶ 通信服務程序/通信服務對象
通信服務程序和通信服務對象的主要功能相同,都是管理模塊的注冊與注銷,并負責把發(fā)送給它的事件轉發(fā)到已注冊的相關模塊中。區(qū)別在于通信服務程序管理進程間的模塊通信,而通信服務對象管理進程內的模塊通信。
void RegisterModule(); //模塊注冊
void UnregisterModule(); //模塊注銷
void DispatchNewsEvent(NewsEvent* event); //轉發(fā)模塊事件
事件在進程間和進程內傳遞方式的區(qū)別由通信框架進行封裝,對模塊而言,它面向的是統(tǒng)一的軟件通信框架,只需要按照框架規(guī)范開發(fā),就可以進行通信。
4 結束語
本文描述了一種軟件通信框架的設計過程,并給出了一個較為簡單的通信框架實現(xiàn)。它基于面向對象的設計方法,使用C++編程語言,利用Qt開發(fā)庫來進行實現(xiàn)。使用基于統(tǒng)一事件模型的軟件通信框架可以減少模塊通信復雜度,縮短軟件通信功能開發(fā)周期,提高軟件可維護性,而且利于擴展和移植。然而面對軟件系統(tǒng)中繁多的通信需求,目前還無法在本框架內考慮周全,只有在不斷迭代細化框架的過程中,才能使問題逐一明了。目前,此軟件通信框架已在“NEWS油氣勘探綜合解釋系統(tǒng)”中得到應用,能完全滿足解釋系統(tǒng)需求,應用效果較好。
參考文獻:
[1] 王宏琳.地球物理軟件體系結構研究[J].石油地球物理勘探,2008.43
(5):606-611
[2] 李卓桓.Linux網(wǎng)絡編程[M].機械工業(yè)出版社,2000.
[3] C.Thomas Wu.面向對象程序設計導論[M].電子工業(yè)出版社,2000.
[4] Xteam軟件技術有限公司.Qt程序設計[M].清華大學出版社,2002.
[5] 錢能.C++程序設計教程[M].清華大學出版社,1999.