曹建平,朱國濤,孫文柱,胡文婷
(海軍航空大學 青島校區(qū),山東 青島 266000)
為提高性能和費效比,大型復雜計算常常采用分布式方式進行[1]。分布式系統(tǒng)作為一個體系,一般包括多個異構(gòu)的子系統(tǒng),各子系統(tǒng)的多樣性、異構(gòu)性為集成工作帶來很大挑戰(zhàn),因此建立統(tǒng)一的系統(tǒng)集成框架具有重要意義。該框架不但要保證系統(tǒng)集成達到低耦合、擴展性、易配置和實時性等要求,還要有效提高開發(fā)、升級和維護效率。
當前,對于分布式異構(gòu)系統(tǒng)的集成方法和框架包括:應(yīng)用于分布式仿真的分布式交互仿真(distributed interactive simulation,DIS)框架和高層體系結(jié)構(gòu)(high level architecture,HLA)框架,目前已形成IEEE標準[2],并有多種軟件實現(xiàn),在軍事仿真領(lǐng)域應(yīng)用廣泛;基于XML、SOAP和WSDL技術(shù)的Web Service框架[3],可實現(xiàn)異構(gòu)的分布式web應(yīng)用進行實時交互,在軟件實現(xiàn)上包括微軟.NET,IBM的WebSphere和Borland的JBuilder等,在電子商務(wù)、電子政務(wù)和游戲領(lǐng)域應(yīng)用廣泛;以數(shù)據(jù)為中心,采用虛擬總線的“發(fā)布-訂閱”通信模式,強調(diào)高可靠性和實時性的數(shù)據(jù)分發(fā)服務(wù)(Data Distribution Service)框架[4],通過21種QoS服務(wù)質(zhì)量策略能很好支持異構(gòu)設(shè)備之間數(shù)據(jù)分發(fā)和傳輸,包括OpenDDS、OpenSpliceDDS等軟件實現(xiàn),廣泛應(yīng)用于國防、民航和工業(yè)控制領(lǐng)域;在物聯(lián)網(wǎng)領(lǐng)域還包括AMOP、XMPP、MQTT和COAP等框架和實現(xiàn)。Michael等為集成多種異構(gòu)模擬器提供了一種名為Ptolemy II的集成環(huán)境;Silva T W B[5]等針對異構(gòu)的硬件平臺環(huán)境,基于HLA協(xié)議,在聯(lián)邦大使和應(yīng)用程序之間提出一種通用的松耦合的虛擬總線(Virtual Bus)計算平臺,達到了提高集成效率的目的;朱曉攀[6]等根據(jù)像質(zhì)處理提升仿真系統(tǒng)需求提出了采用數(shù)據(jù)分發(fā)服務(wù)(data distributed service,DDS)技術(shù)進行集成,實現(xiàn)海量圖像和數(shù)據(jù)傳輸?shù)陌葱璺峙洹崟r性、可靠性、擴展性和高吞吐率要求。
以上框架和相應(yīng)的實現(xiàn)在各自領(lǐng)域都達到了系統(tǒng)集成框架的功能和性能要求,但在細分領(lǐng)域還需要進行定制開發(fā),存在一定的開發(fā)和維護難度。為此,針對分布式飛行仿真提出了一種新的分布式異構(gòu)系統(tǒng)集成方法和框架,并利用C++原生語言進行了實現(xiàn)。該框架在某型飛機分隊戰(zhàn)術(shù)模擬訓練中得到了應(yīng)用,應(yīng)用結(jié)果表明該框架可用于互聯(lián)包括視景顯示計算機、飛行控制計算機、教員控制臺、計算機生成兵力等多種異構(gòu)實體,具有低耦合、擴展性強、易配置和實時性高的優(yōu)點。該框架還可應(yīng)用于其他類似的輕量級分布式實時應(yīng)用的異構(gòu)集成。
對于大型的分布式系統(tǒng),系統(tǒng)之間的關(guān)系比較復雜,傳統(tǒng)一般采取如圖1所示的緊耦合方式進行集成。這種設(shè)計對系統(tǒng)的開發(fā)、升級和擴展都不利,尤其在增加新的系統(tǒng)或數(shù)據(jù)時(圖1中的虛線)時非常困難,隨著系統(tǒng)復雜度的增加甚至會造成整個分布式系統(tǒng)的崩潰。因此,采取松散耦合的方式進行系統(tǒng)集成已經(jīng)成為共識。

圖1 傳統(tǒng)設(shè)計的緊耦合網(wǎng)絡(luò)
為破除系統(tǒng)之間的緊耦合關(guān)系,在系統(tǒng)之間添加一個分發(fā)服務(wù)器,每個系統(tǒng)通過分發(fā)服務(wù)器進行交互,如圖2所示。該設(shè)計的基本思想就是將各系統(tǒng)的數(shù)據(jù)集中到分發(fā)服務(wù)器上,同時分發(fā)服務(wù)器又實時地將數(shù)據(jù)分發(fā)給各子系統(tǒng),從而達到了分布式系統(tǒng)數(shù)據(jù)在各子系統(tǒng)間的共享。各子系統(tǒng)都包含了一個解析子模塊,負責對共享的數(shù)據(jù)進行過濾和解析,這樣各子系統(tǒng)在升級或添加新的子系統(tǒng)時只需要更新解析子模塊即可,從而達到了系統(tǒng)之間的松耦合,將這種數(shù)據(jù)集成方式稱為“集中-分發(fā)”模式。
該設(shè)計中的分發(fā)服務(wù)器與DDS技術(shù)中的“虛擬總線”概念有所類似,都是為了達到子系統(tǒng)間數(shù)據(jù)共享的目的,但實際上是有區(qū)別的,主要體現(xiàn)為兩點:一是DDS中的“總線”是虛擬的,實際上是通過網(wǎng)絡(luò)中間層實現(xiàn)的,而本設(shè)計是存在一個確定且獨立運行的分發(fā)服務(wù)器;二是DDS的“虛擬總線”核心是“發(fā)布-訂閱”模式,而本設(shè)計是將分布式系統(tǒng)中的所有數(shù)據(jù)送到各子系統(tǒng),由各子系統(tǒng)過濾解析獲取需要的數(shù)據(jù)。之所以采取這種方式還是由于面向的是輕量級應(yīng)用,雖然通過“發(fā)布-訂閱”方式可減少數(shù)據(jù)冗余,但對數(shù)據(jù)傳輸效率帶來不良影響且對系統(tǒng)的可擴展也不利。

圖2 基于“集中-分發(fā)”模式的松散耦合設(shè)計
在該模式中,分發(fā)服務(wù)器處于核心位置,要實現(xiàn)分發(fā)服務(wù)器與所有子系統(tǒng)進行交互要求分發(fā)服務(wù)器功能單一,即只完成數(shù)據(jù)的分發(fā),不涉及到數(shù)據(jù)的具體內(nèi)容,分發(fā)服務(wù)器與各子系統(tǒng)之間不存在任何額外的協(xié)議。因此,對于各子系統(tǒng)而言,分發(fā)服務(wù)器實際上相當于一個快遞公司,只負責郵件(數(shù)據(jù))的托運而沒有權(quán)限查看或處理郵件的內(nèi)容。這是達到松散耦合的一個必要條件,但不是充分條件。原因在于,雖然分發(fā)器對傳輸數(shù)據(jù)的內(nèi)容是無關(guān)的,但卻對傳輸數(shù)據(jù)的大小是敏感的,因此需對分布式系統(tǒng)的單次傳輸量進行統(tǒng)一規(guī)定。這樣,分發(fā)服務(wù)器就成為了一個特殊的快遞公司,它只接收具有固定大小的郵件并將其發(fā)送到所有想接收這個郵件的客戶(各子系統(tǒng))手里。對于一個子系統(tǒng)而言,需將其單位業(yè)務(wù)數(shù)據(jù)包的大小包裝成分發(fā)器傳輸規(guī)定的大小。要完成松散耦合,另一個必要條件是各子系統(tǒng)能正確過濾和解析從分發(fā)器發(fā)送過來的數(shù)據(jù)。為實現(xiàn)該功能,在分發(fā)服務(wù)器中設(shè)置一個緩沖區(qū)域,在該區(qū)域中各子系統(tǒng)數(shù)據(jù)的相對位置是固定的,對各子系統(tǒng)進行編號,將編號和位置建立一一映射。這樣,某一個子系統(tǒng)就可以通過編號設(shè)置接收哪些子系統(tǒng)的數(shù)據(jù),并根據(jù)相對位置找到對應(yīng)的數(shù)據(jù)并進行解析。該過程通過配置文件實現(xiàn),為系統(tǒng)的可擴展提供了可能。另外,分發(fā)服務(wù)器緩沖區(qū)域在場景運行之前就是固定好不能更改的,分發(fā)服務(wù)器中的接收和發(fā)送線程通信采用“best-effort”模式,只要緩沖區(qū)域內(nèi)有數(shù)據(jù)就發(fā)送,從而可以適應(yīng)不同子系統(tǒng)的發(fā)送接收數(shù)據(jù)頻率的差異性。
為此,在分發(fā)服務(wù)器和子系統(tǒng)之間還需要設(shè)置一個中間件完成上述工作。該中間件具有3個作用:1)將本地單位業(yè)務(wù)數(shù)據(jù)包裝成符合傳輸要求的數(shù)據(jù);2)過濾和解析遠程子系統(tǒng)數(shù)據(jù);3)進行數(shù)據(jù)傳輸。如圖3所示,根據(jù)中間件功能,中間件可劃分為3個模塊,分別是數(shù)據(jù)打包模塊、數(shù)據(jù)解析模塊和數(shù)據(jù)傳輸模塊。整個數(shù)據(jù)流過程是:打包模塊負責將子系統(tǒng)的數(shù)據(jù)打包成符合分發(fā)服務(wù)器規(guī)定大小的數(shù)據(jù)包并通過傳輸模塊中的發(fā)送線程將本地數(shù)據(jù)發(fā)送到分發(fā)服務(wù)器;而傳輸模塊中的接收線程負責接收分發(fā)服務(wù)器發(fā)送的整個分布式系統(tǒng)的共享數(shù)據(jù),并由解析模塊對共享數(shù)據(jù)進行過濾和解析。中間件可以以多種方式集成到子系統(tǒng)中,既可以打包成動態(tài)鏈接庫由子系統(tǒng)調(diào)用,也可以是一個單獨的進程與子系統(tǒng)進行數(shù)據(jù)交互。

圖3 中間件的模塊劃分與數(shù)據(jù)流
由上可知,分發(fā)服務(wù)器是業(yè)務(wù)無關(guān)的,而子系統(tǒng)是通過中間件來分享分布式系統(tǒng)的數(shù)據(jù),因此當一個新的子系統(tǒng)加入分布式系統(tǒng)時只需要定制中間件中的解析模塊即可實現(xiàn),從而實現(xiàn)了子系統(tǒng)間數(shù)據(jù)集成的松散耦合。
面向輕量級的分布式實時應(yīng)用,根據(jù)基于“集中-分發(fā)”模式的異構(gòu)數(shù)據(jù)集成方法,實現(xiàn)了數(shù)據(jù)集成框架,總體框架如圖4所示。在該框架下,將分布式應(yīng)用的整個運行過程稱為場景,將場景中的每個子系統(tǒng)稱為參與者,每個參與者有一個角色屬性(參與者括號的內(nèi)容),根據(jù)角色屬性可確定其業(yè)務(wù)數(shù)據(jù)類型。根據(jù)數(shù)據(jù)流方向,將框架分為3個部分:由參與者組成的參與者集、分發(fā)服務(wù)器、嵌入了中間件的中間層。原生的中間件是一個動態(tài)鏈接庫,可以采用多種方式與參與者集成,圖4給出了常見的4種方式:1)參與者程序直接調(diào)用中間件動態(tài)庫;2)將中間件動態(tài)庫封裝成為一個獨立的程序,通過網(wǎng)絡(luò)與參與者進行通信;3)參與者基于高層體系結(jié)構(gòu)(HLA)開發(fā),則將中間件封裝成為一個聯(lián)邦成員,通過HLA/RTI通信;4)參與者是一種多Agent體系結(jié)構(gòu),則可將中間件封裝成為一個Agent,通過多Agent系統(tǒng)中的通用黑板(GBB)進行通信。
分發(fā)服務(wù)器則有兩部分組成,分別是分發(fā)模塊和緩沖區(qū)。每一個參與者按順序?qū)?yīng)緩沖區(qū)的一個子區(qū)域,每個子區(qū)域存儲對應(yīng)參與者的實時狀態(tài)。每個子區(qū)域又對應(yīng)分發(fā)模塊中的IO線程,IO線程負責與對應(yīng)的中間件進行網(wǎng)絡(luò)通信,從而更新緩沖區(qū)子區(qū)域中的參與者實時狀態(tài)。
場景中的參與者對數(shù)據(jù)需求是不同的,有的只生產(chǎn)數(shù)據(jù),有的只消費數(shù)據(jù),有的既生產(chǎn)也消費數(shù)據(jù)。因此,在分發(fā)服務(wù)器中分發(fā)模塊分為只寫模式、只讀模式、讀寫模式,只寫模式對應(yīng)一個寫線程,只讀模式對應(yīng)一個讀線程,讀寫模式對應(yīng)一個寫線程和一個讀線程。寫線程從中間件讀取參數(shù)者數(shù)據(jù)并存儲到緩沖區(qū)對應(yīng)子區(qū)域;讀線程讀取整個緩沖區(qū)實時狀態(tài)并發(fā)送到對應(yīng)參數(shù)者的中間件。緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)也是可以定制的,一種是采用先進先出的鏈表結(jié)構(gòu)以保留歷史數(shù)據(jù);另一種緩沖區(qū)空間固定,只保留實時最新狀態(tài)。
該框架可柔性適應(yīng)多種場景,原因就在于分發(fā)服務(wù)器和中間件是可配置的。對于分發(fā)服務(wù)器,需要配置的必要信息有場景中的參與者數(shù)目、每個參與者的IO模式、每個參與者的網(wǎng)絡(luò)地址、每個參與者聯(lián)接的網(wǎng)絡(luò)協(xié)議和單次傳輸數(shù)據(jù)大??;對于中間件,需要配置感興趣的參與者的順序號及其角色、分發(fā)服務(wù)器網(wǎng)絡(luò)地址、單次傳輸數(shù)據(jù)大小。從配置信息可以看出,分發(fā)服務(wù)器不關(guān)心參與者的角色信息,中間件為解析數(shù)據(jù)必須要知道對應(yīng)參與者的角色信息。
該框架下,參與者之間不直接互聯(lián),而是以分發(fā)服務(wù)器為中心進行數(shù)據(jù)交互。因此可實現(xiàn)增量開發(fā),即在場景中增刪參與者時只需要完善配置信息并對中間件進行簡單的二次定制即可實現(xiàn)。

圖4 基于“集中-分發(fā)”模式的數(shù)據(jù)集成架構(gòu)
該框架包括兩個軟件模塊,分別是分發(fā)服務(wù)器和中間件。按照本框架,這兩個軟件模塊具有多種實現(xiàn)方式,本文利用C++語言進行了實現(xiàn),下面分別予以介紹。
按照框架要求,分發(fā)服務(wù)器除了緩沖區(qū)、分發(fā)模塊以外還需要有配置功能和網(wǎng)路傳輸功能,因此分發(fā)服務(wù)器還包括配置子模塊和網(wǎng)絡(luò)傳輸子模塊,模塊劃分如圖5所示。配置子模塊主要用來讀取配置文件,在正式運行之前為分發(fā)子模塊和緩沖區(qū)子模塊配置好相關(guān)參數(shù)。網(wǎng)絡(luò)運輸子模塊封裝了WinSock的一些常用函數(shù),以動態(tài)鏈接庫的形式給出。緩沖區(qū)子模塊給出了存儲緩存各參與者傳輸數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。分發(fā)模塊處于分發(fā)器的核心,由配置子模塊配置其相關(guān)參數(shù),并調(diào)用網(wǎng)絡(luò)傳輸子模塊傳輸數(shù)據(jù)并對緩沖區(qū)子模塊進行更新,完成節(jié)點間的數(shù)據(jù)分發(fā)。

圖5 分發(fā)服務(wù)器的模塊劃分
3.1.1 配置子模塊實現(xiàn)
分發(fā)服務(wù)器采用ini文件方式配置,程序中采用類的方式進行封裝。類中的成員變量是配置參數(shù),由于程序中需且僅需一個參數(shù),因此都是靜態(tài)變量。成員函數(shù)_initialConfigParams是讀取相應(yīng)的配置文件為配置參數(shù)賦值。
3.1.2 網(wǎng)絡(luò)傳輸子模塊實現(xiàn)
為了重用代碼,將winsock的一些常用函數(shù)封裝為類,類繼承關(guān)系如圖6所示。

圖6 網(wǎng)絡(luò)傳輸子模塊類圖
其中,socketBaseClass作為基類,主要封裝了本地和遠程地址以及Init、send和Receive三個成員函數(shù),在基類中Init、Send和Receive是虛函數(shù),需要在子類中進行重寫。socketUDPClass對UDP協(xié)議相關(guān)的函數(shù)進行了封裝,基類繼承了相關(guān)變量并對Init、Send和Receive進行了重寫。由于UDP是不分服務(wù)端和客戶端的,所以只要一個類就可以實現(xiàn)。socketTCPClientClass和socketTCPServerClass封裝了TCP協(xié)議的相關(guān)函數(shù)。對于TCP而言,服務(wù)器端和客戶端的初始化過程是不同的,因此封裝為兩個類。
3.1.3 緩沖區(qū)子模塊實現(xiàn)
按照緩沖發(fā)送模式的要求,在分發(fā)器中設(shè)置一個緩沖區(qū)用來暫存各參與者的狀態(tài)數(shù)據(jù)。如圖7所示,當要聯(lián)入m個參與者時,緩沖區(qū)就平均分為m塊,每一塊用來緩存對應(yīng)參與者各狀態(tài)的數(shù)據(jù)。

圖7 分發(fā)器緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)
實現(xiàn)時整個緩沖區(qū)作為一個數(shù)組,數(shù)組的成員又是一個先進先出的隊列結(jié)構(gòu),而隊列中的每個成員又是指向?qū)嶋H狀態(tài)數(shù)據(jù)內(nèi)存的指針。因此,利用標準C++的STL庫,將程序中的緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)聲明如下:
由于目前聯(lián)網(wǎng)的參與者的數(shù)目是事先確定的,因此緩沖區(qū)數(shù)組的大小是一定的,也就是說對應(yīng)參與者的隊列是在聯(lián)網(wǎng)運行前已經(jīng)確定好了。在聯(lián)網(wǎng)分發(fā)過程中變化的只有隊列中的元素,也就是要對隊列進行壓入數(shù)據(jù)與彈出數(shù)據(jù)操作。對于壓入數(shù)據(jù)是比較簡單的,當某一個參與者狀態(tài)數(shù)據(jù)傳入時就壓入緩沖區(qū)對應(yīng)隊列的頭部;而彈出數(shù)據(jù)相對要復雜一些,原因就在于該數(shù)據(jù)要傳到除自身以外的所有參與者處后才能彈出。
為了實現(xiàn)這個邏輯,為隊列的每一個成員即參與者的狀態(tài)數(shù)據(jù)結(jié)構(gòu)加了一個頭部,該頭部作為標志位數(shù)組是由一定數(shù)目的整數(shù)類型組成的,該數(shù)組的大小與參與者數(shù)目相同,數(shù)組中的數(shù)值取1時表示該狀態(tài)數(shù)據(jù)已發(fā)送到所在位置的參與者處,否則表示還沒有發(fā)送,當標志位全部為1時表示數(shù)據(jù)全部發(fā)送到位,程序會自動刪除該狀態(tài)數(shù)據(jù),即完成了隊列狀態(tài)數(shù)據(jù)的彈出操作。
3.1.4 分發(fā)子模塊實現(xiàn)
如圖5可知,分發(fā)子模塊是分發(fā)器的核心模塊,其具體負責將接收到的參與者狀態(tài)數(shù)據(jù)分發(fā)到其他參與者處。分發(fā)子模塊是由上游子模塊和下游子模塊兩部分組成的,上游子模塊負責接收某一個參與者的狀態(tài)數(shù)據(jù)并將其寫入緩沖區(qū)內(nèi),而下游子模塊負責讀取其他參與者的狀態(tài)數(shù)據(jù)并發(fā)送回參與者處,如圖8所示。

圖8 分發(fā)子模塊組成
由圖8所示,根據(jù)“生產(chǎn)者-消費者模式”,在上游子模塊和上游子模塊中都存在一個數(shù)據(jù)緩沖區(qū),該緩沖區(qū)主要目的也是為了分離收線程與寫線程或者讀線程與發(fā)線程之間的耦合關(guān)系,使其不相互依賴從而達到提高效率的目的。
分發(fā)子模塊中的收線程、寫線程、發(fā)線程和讀線程都是獨立運行的線程,并且可知,在整個訓練過程當中,線程數(shù)目是一定的(與場景中的參與者數(shù)目成正比),并且各個線程一旦開始運行就不會停下來,直到程序終止,也就是不會頻繁地進行創(chuàng)建和消除,從而節(jié)省了調(diào)度時間,提高了分發(fā)效率。在程序開發(fā)過程中,涉及的開發(fā)難度主要體現(xiàn)在線程之間的同步,在程序?qū)崿F(xiàn)過程當中主要采用關(guān)鍵代碼段的方式來實現(xiàn)的。
在4個線程當中,收線程、寫線程和發(fā)線程的邏輯相對比較簡單,重點描述一下讀線程。讀線程需要額外完成上文提到的數(shù)據(jù)彈出邏輯。讀線程主體是一個while循環(huán),首先申請存放讀取數(shù)據(jù)的內(nèi)存區(qū)并將其初始化為0,接著依次讀取緩沖區(qū)成員,當某個緩沖區(qū)成員隊列不為空是從隊列尾部開始向前遍歷讀取狀態(tài)數(shù)據(jù),讀取時首先判讀對應(yīng)標志位是否以置為1,如果是的話就繼續(xù)向前遍歷直到遇到標志位為0的隊列成員,將該隊列數(shù)據(jù)存到內(nèi)存區(qū)域且設(shè)置標志位為1,最后判斷該狀態(tài)的標志位是否都為1,如果是則將該狀態(tài)數(shù)據(jù)彈出。其總體流程如圖9所示。

圖9 讀線程邏輯流程圖
由圖4體系結(jié)構(gòu)可知,中間層主要實現(xiàn)參與者與分發(fā)服務(wù)器之間的數(shù)據(jù)傳輸、打包與解析。對于不同角色的參與者而言,由于整個場景中的單次傳輸數(shù)據(jù)大小是相同的,因此傳輸模塊和打包模塊是固定不變的。而參與者角色有所不同,因此解析模塊是可定制的,從而實現(xiàn)將傳輸數(shù)據(jù)轉(zhuǎn)化為業(yè)務(wù)數(shù)據(jù)。
3.2.1 傳輸模塊的實現(xiàn)
傳輸模塊的組成如圖10所示,可以看到傳輸模塊的組成與分發(fā)服務(wù)器器的分發(fā)子模塊的組成是類似的,不同之處在于寫線程變成了寫函數(shù),而讀線程變成了讀函數(shù)。參與者在集成中間層時,只需要周期性調(diào)用寫函數(shù)和讀函數(shù),就可以完成數(shù)據(jù)的接收與發(fā)送。

圖10 傳輸模塊組成
傳輸模塊中的發(fā)送數(shù)據(jù)區(qū)和接收數(shù)據(jù)區(qū)也是以隊列的數(shù)據(jù)結(jié)構(gòu),寫函數(shù)、發(fā)線程、讀函授和收線程之間的同步依然是通過關(guān)鍵代碼段。
3.2.2 解析模塊實現(xiàn)
在分發(fā)模塊和傳輸模塊中沒有涉及到各參與者的業(yè)務(wù)數(shù)據(jù),這樣就非常有利于擴展參與者的角色。解析模塊就負責將傳輸數(shù)據(jù)轉(zhuǎn)換為程序能夠處理的業(yè)務(wù)數(shù)據(jù)。
我們知道,在內(nèi)存塊中數(shù)據(jù)都是以0、1的形式存在的,在沒有上下文的情況下是沒有任何意義的,但當我們?nèi)〉媚骋粔K內(nèi)存的地址并將其解釋為事先定義好的數(shù)據(jù)結(jié)構(gòu),那么這塊內(nèi)存的數(shù)據(jù)就能得到解析了,如圖11所示。

圖11 利用定義好的結(jié)構(gòu)體解析內(nèi)存塊
傳輸模塊類中定義的接收數(shù)據(jù)區(qū)是一大塊數(shù)據(jù),它包含了所有遠程參與者的狀態(tài)數(shù)據(jù),將參與者ID號與接收數(shù)據(jù)區(qū)的內(nèi)存塊建立一一對應(yīng)的關(guān)系,通過參與者的ID號就能找到對應(yīng)的數(shù)據(jù)塊。如圖12所示,由于單次傳輸數(shù)據(jù)大小是一定的,因此在分發(fā)器緩沖區(qū)被均分為N塊(N是參與者數(shù)目),每一塊的大小都是單次傳輸數(shù)據(jù)大小。那么分發(fā)器內(nèi)緩沖區(qū)的數(shù)據(jù)排列都是按照配置文件中參與者ID數(shù)組給出的順序排列,那么數(shù)據(jù)由分發(fā)器發(fā)往某個參與者時前后順序仍然是不變的(注意此時本地參與者數(shù)據(jù)不會發(fā)到本地參與者),那么再通過本地參與者定義的配置文件中的遠程參與者數(shù)組所規(guī)定的順序就可以找到對應(yīng)ID遠程參與者數(shù)據(jù)地址了。

圖12 參與者ID號與內(nèi)存塊中數(shù)據(jù)一一映射關(guān)系
為便于實現(xiàn)解析過程,提供了一個遠程參與者類,如圖13所示。類中給出了5種默認的參與者角色,分別是模擬器角色、教控臺角色、引導臺角色、VRForce產(chǎn)生的虛擬兵力角色和MaxSim產(chǎn)生的虛擬兵力角色。如果在場景中要加入新的角色,只要繼承該類并在字段中添加要擴展的參與者的業(yè)務(wù)數(shù)據(jù)結(jié)構(gòu)并重寫initFromIni()函數(shù)即可。

圖13 遠程參與者類結(jié)構(gòu)
某型飛機分隊戰(zhàn)術(shù)模擬訓練系統(tǒng)是面向單機、雙機、四機及以上相同或不同機型開展戰(zhàn)術(shù)協(xié)同訓練科目而開發(fā)的。該系統(tǒng)由多個模擬器、教員臺、引導臺、虛擬兵力、態(tài)勢監(jiān)控等多個異構(gòu)子系統(tǒng)組成,如何將這些異構(gòu)的子系統(tǒng)進行有效的數(shù)據(jù)集成并滿足系統(tǒng)間數(shù)據(jù)交互的實時性和可靠性是開發(fā)分隊戰(zhàn)術(shù)模擬訓練系統(tǒng)的一個重點和難點。采用本文提供的分發(fā)服務(wù)器和中間層軟件進行了集成,集成后網(wǎng)絡(luò)結(jié)構(gòu)如圖14所示。

圖14 某型飛機分隊戰(zhàn)術(shù)模擬訓練系統(tǒng)網(wǎng)絡(luò)結(jié)構(gòu)
從該網(wǎng)絡(luò)結(jié)構(gòu)可以看出,該系統(tǒng)參與者數(shù)目N=12,參與者的角色有5種:模擬器(編號1到6)、引導臺(編號7、8)、VRForce計算機生成兵力平臺(編號9)、MaxSim計算機生成兵力平臺(編號10)、教員臺(編號11)和態(tài)勢監(jiān)控(編號12)。為每種角色的業(yè)務(wù)數(shù)據(jù)定義特定的數(shù)據(jù)結(jié)構(gòu)。
按照本文給出的方法集成的某型飛機分隊戰(zhàn)術(shù)模擬訓練系統(tǒng)已經(jīng)在部隊得到了初步的應(yīng)用,實踐表明,該方法能夠?qū)悩?gòu)的子系統(tǒng)快速進行集成并滿足通信的實時性和可靠性要求。
本文旨在為連接節(jié)點數(shù)目不多、數(shù)據(jù)吞吐量不大,但數(shù)據(jù)交互實時性要求高的輕量級的分布式應(yīng)用場景提供一種易使用的系統(tǒng)集成方法、框架和實現(xiàn)。從設(shè)計和使用看,本文給出的框架具有模塊化、可擴展性和可配置性的優(yōu)點。并且所有代碼都是基于C++標準庫完成,因此具有跨平臺的特點。下一步可進一步提高分發(fā)服務(wù)器的柔性,達到根據(jù)參與者的請求進行自動配置的功能。