jphone項目設計介紹(一個基於C++的應用程序框架以及軟電話和日誌服務器應用)

一、源碼路徑

https://github.com/weiganyi/jphone

 

二、界面截圖

由於應用程序框架本身沒有界面,所以這裏顯示一下基於應用程序框架開發的兩個應用程序的界面。

軟電話界面:


日誌服務器界面:



三、背景

最開始做這個項目的時候,是由於發現了一個叫PjSIP的開源SIP協議棧,實現上要比OSIP成熟許多,用它來開發SIP應用也更簡單方便,我就考慮基於PjSIP來做一個SIP軟電話原型。

我選擇用C++語言來實現,原因是我想要在這個項目中實現一些通用機制,C++語言比那些解釋語言更適於底層開發,同時C++的語言特性也要比C語言豐富許多。

軟件界面這塊我用VC來做,但是我之前只用過VC6,新的VC版本沒有用過,考慮到這只是一個原型產品,界面難看點關係不大,本着界面能用就行的原則,還是使用VC6來做界面。

對於軟件配置的存儲,採用本地文件和MySQL數據庫並行的方式,主要考慮還是想提供多樣化的選擇。

項目分了兩個階段,第一階段我把這個SIP軟電話原型實現了,也實現了一些基本的通用機制。後來隨着自己對軟件系統架構理解的積累,我考慮着要把那些通用機制增強成一些通用組件框架,並且能夠基於這個組件方便的開發其它的應用程序,這就對組件的通用性提出了更高的要求。第二階段我進行了代碼重構和增強,實現了一個通用的應用程序組件框架。爲了驗證組件框架的通用性,除了原來基於它實現的SIP軟電話原型(單線程模式)外,我還實現了一個日誌服務器原型(多線程模式)。

對於操作系統接口的使用,目前直接使用的Windows的接口,後續如果要做多操作系統兼容,可以再對操作系統接口進行封裝,這是個工作量問題。

 

四、功能實現

項目的功能實現分以下三部分:

1、實現通用的應用程序組件框架,封裝操作系統的基本接口,不依賴第三方庫實現開發其它應用程序所需的各類組件模塊,提供方便的使用接口。

2、實現SIP軟電話原型,能夠通過軟件界面操作完成基本通話,支持基本的配置參數,發起呼叫可以通過號碼按鍵或點擊最近通話號碼的方式進行。

3、實現日誌服務器原型,支持最多10個日誌客戶端的同時連接,並能顯示選中連接上接收的日誌,支持基本的配置參數。

 

五、總體設計思路

1、組件框架包含了幾十個類,所以設計了一個類的繼承體系樹,從最基本JObject根類派生出其他各式各樣的類。把同一類功能的類封裝在一個模塊裏,對於每個模塊,如果有多種類型的類就要定義一個抽象基類來定義它們的接口。

2、通過一系列通用模塊來構成應用程序組件框架,如:模塊、異常、智能指針、鎖、單件、字符串、日誌、內存管理、定時器、通信、消息路由、事件、鏈表、隊列、持久化、後臺任務、線程管理等。

3、基於應用程序組件框架,通過增加上層的SipUa模塊和代理模塊就能實現出SIP軟電話,通過增加上層的日誌服務器模塊和代理模塊就能實現出日誌服務器。

4、爲了避免名字污染,對於應用程序組件框架的各個模塊,都包含在JFrameWork的名字空間裏。在SIP軟電話和日誌服務器裏,要把這個名字空間引用進來。

5、應用程序的配置存儲支持Ini文件、Xml文件、MySQL三種方式,根據JDaemon後臺任務的配置文件jdaemon_cfg.ini來決定採用哪種方式。

6、組件框架內部定義了進程、線程、模塊三個級別。對於SIP軟電話和日誌服務器進程,包含的線程有:JModuleThread線程、JTimer線程、JPjSipUa線程、JPhoneAgent線程、JLogServerAgent線程、JLogSrvThread線程、JLogMsgThread線程。對於JModuleThread線程,包含的模塊有:JStaticMemory模塊、JLog模塊、JTimer模塊、JDaemon模塊、JPjSipUa模塊。

7、考慮組件框架要支持相對複雜的應用程序,對於線程和模塊之間的通信,採用Actor模式的消息串行通信方式,最大限度減少線程和模塊之間鎖的使用,提高併發性。

8、線程內定義模塊這個級別,主要是爲了能夠通過配置模塊優先級來在線程內對模塊進行執行調度,實現類似協程的機制來減少線程調度的發生,提高系統性能。

9、一些核心模塊採用定義全局單件對象的方式方便訪問,並用鎖保護共享數據訪問。

 

六、文件及類的設計

JObject.cpp/h:

virtual class JObject

所有類的基類,包含基本數據類型封裝和通用字符串處理。

virtual class JModule: public JObject

模塊基類,包含初始化和事件處理等接口,供各種模塊類繼承。

class JException: public JObject

異常處理類,用於異常處理時拋出的異常對象。

virtual class JEventBody: public JObject

事件體基類,包含克隆、序列化、反序列化等接口,可以派生出各種類型的事件體類。


JAutoPtr_T.cpp/h:

template<class TYPE> classJAutoPtrBase: public JObject

智能指針模板基類,包含成員訪問接口。

template<class TYPE> class JAutoPtr:public JAutoPtrBase<TYPE>

智能指針模板類,增加賦值操作符。


JAutoPtr.cpp/h:

智能指針模板類函數特化,針對鎖類型進行函數特化處理。


JDaemon.cpp/h:

class JDaemonCfg: public JEventBody

後臺任務配置類,包含了後臺任務類的配置,用於事件通信。

class JDaemon: public JModule

後臺任務類,作爲一個模塊獨立運行,目前主要作用於設置和獲取系統配置的存儲方式,後續可擴展承載其他系統級任務。


JEvent.cpp/h:

class JEvent: public JObject

事件類,包含源地址和目的地址,通過進程名、線程名、模塊名三元組共同標明一個地址,並通過事件體指針來包含具體的事件體內容。


JList_T.cpp/h:

template<class Type> class JListItem:public JObject

列表項模板類,存儲具體的內容對象,並且保持與其它列表項的鏈接。

template<class TYPE> classJListIterator: public JObject

列表迭代器模板類,能夠對一個列表模板類對象進行迭代訪問。

template<class Type> class JList:public JObject

列表模板類,包含對列表的各種類型訪問。

template<class Type> class JQueue:public JObject

隊列模板類,以列表模板類爲基礎,實現的一個隊列以及相應的隊列操作。


JList.cpp/h:

列表項模板類函數特化,針對堆內存、事件類、哈希數據類型進行函數特化處理,列表模板類函數特化,針對持久化記錄類型進行函數特化處理。


JLock.cpp/h:

class JLock: public JObject

鎖同步對象類,封裝了操作系統的臨界區對象,提供線程間的互斥訪問保護。


JLog.cpp/h:

class JFmt: public JObject

格式類,存儲當前日誌打印的模塊和級別。

class JLogDecorator: public JObject

日誌裝飾基類,用於日誌輸出時的裝飾模式。

class JLogTimeDecorator: publicJLogDecorator

日誌時間裝飾類,在日誌輸出時添加上時間戳。

class JLogOutput: public JObject

日誌輸出基類,定義了日誌輸出和裝飾的接口。

class JLogOutputLocal: public JLogOutput

日誌控制檯輸出類,向串口控制檯輸出日誌信息。

class JLogOutputFile: public JLogOutput

日誌文件輸出類,向本地文件輸出日誌信息。

class JLogOutputRemote: public JLogOutput

日誌遠端輸出類,採用TCP連接遠程的日誌服務器,向服務器發送日誌信息。

class JLogCfg: public JEventBody

日誌配置類,包含了日誌類的配置,用於事件通信。

class JLog: public JObject

日誌類,定義了各種日誌輸出的操作符,通過模塊和級別來控制日誌輸出,能採用控制檯、文件、遠程三種方式輸出日誌,並使用裝飾模式來裝飾日誌信息,可以跟蹤記錄函數調用序列,同時啓動定時器來維護遠程日誌的TCP連接。

class JLogAutoPtr: publicJAutoPtrBase<JLog>

智能指針模板日誌特化類,利用智能指針的構造和自動析構特性來記錄函數進入和退出日誌信息。


JMemory.cpp/h:

virtual class JMemory: public JObject

內存管理基類,定義了分配、釋放、內存越界檢查、信息打印等接口。

class JTrunkMemory: public JMemory

塊內存管理類,採用預定義不同大小的內存塊池的方式來管理內存分配釋放。

class JHeapMemory: public JMemory

堆內存管理類,採用線性的內存區來分配和釋放內存,彌補超過最大塊內存大小的分配需求。

class JStaticMemory: public JModule

靜態內存管理類,自己管理內存的分配和釋放,內部採用塊和堆兩種管理模式,對分配的內存增加頭尾信息,包含內存分配時的函數調用序列以及校驗字段。啓動定時器通過頭尾校驗字段探測內存寫越界的情況,還能接受命令打印出未釋放的內存信息,包含內存分配時的函數調用序列,供定位內存泄漏問題使用。


JRoute.cpp/h:

class JHash: public JObject

哈希類,提供哈希算法。

class JHashData: public JObject

哈希數據類,存儲路由信息及實現相關操作。

class JRoute: public JObject

路由類,維護路由信息,並通過哈希查找路由類型,在進程內共享


JSerialization.cpp/h:

virtual class JPersistence: public JObject

持久化基類,提供持久化接口,對於數據存儲持久化採用記錄列表類型的參數。

class JIni: public JPersistence

Ini文件持久化類,採用本地Ini文件來存儲持久化數據。

class JMySql: public JPersistence

MySQL持久化類,採用MySQL數據庫來存儲持久化數據,同時數據庫訪問採用MySQL提供的C庫訪問接口,不採用VC的ODBC訪問方法,保證可移植性。

class JMiniXML: public JPersistence

Xml文件持久化類,採用本地Xml文件來存儲持久化數據。

class JSerialization: public JObject

持久化類,根據數據存儲方式對持久化數據進行存儲和獲取。


JSingleton_T.cpp/h:

template<class TYPE> classJSingleton: public JObject

單件模板類,對於進程共享的全局核心對象進行單件化,提供訪問接口。單件類通常包括日誌類、靜態內存管理類、路由類、定時器類、後臺任務類、SipUa類、線程管理類等。


JSocket.cpp/h:

virtual class JSocket: public JObject

Socket基類,定義了數據收發接口。

class JUdpSocket: public JSocket

UDP Socket類,實現了UDP數據的收發和維護。

class JTcpSocket: public JSocket

TCP Socket類,實現了TCP數據的收發和維護。

class JCommEngine: public JObject

通信實體類,能夠進行消息和事件的收發。對於事件,通過路由表對象查找路由,如果是進程內,就將事件發送到線程對象相應模塊的事件隊列中去,如果是進程間,就用UDP Socket發送序列化的事件消息,接收事件時再反序列化爲事件對象。對於消息,直接通過UDP Socket發送接收消息。

class JCommConnector: public JObject

通信連接器類,用於TCP模式Socket客戶端,連接對端服務器,如果成功就返回一個通信實體類進行後續的數據收發。

class JCommAcceptor: public JObject

通信接收器類,用於TCP模式Socket服務器端,監聽本地端口,如果發現客戶端的連接成功就返回一個通信實體類進行後續的數據收發。

class JCommEngineGroup: public JObject

通信實體組類,維護一組通信實體對象,統一探測他們的數據收發事件。


JString.cpp/h:

class JString: public JObject

字符串類,提供對字符串的各類操作接口。


JThread.cpp/h:

virtual class JThread: public JObject

線程基類,定義了線程的事件處理、運行等接口。

class JModuleThread: public JThread

模塊線程類,是組件框架的各模塊的運行載體。這種線程內包含多個模塊,各模塊有獨立事件隊列來接收處理事件,模塊有可配的優先級參數來決定運行策略,各模塊共享一個通信實體對象與其他進程通信。

class JAgentThread: public JThread

代理線程類,代表不屬於組件框架的外部線程與組件框架進行通信。這種線程不包含內部模塊,通過事件隊列來接收處理事件,以及通過通信實體對象與其他進程通信。

class JThreadManager: public JObject

線程管理類,管理各種類型的線程,線程類型和數量可以動態註冊,創建實際線程來運行管理的各個線程,線程間採用異步模式運行。


JTimer.cpp/h:

class JSysTime: public JEventBody

系統時間類,維護系統時間及提供相應的操作接口,用於事件通信。

class JTimer: public JModule

定時器類,只使用一個操作系統定時器資源,通過本身來管理註冊的多個應用定時器。


JSipUa.cpp/h:

class JPjSipUaCfg: public JEventBody

SipUa配置類,包含了SipUa類的配置,用於事件通信。

class JPjSipUaKey: public JEventBody

SipUa按鍵類,封裝了界面的按鍵對象,用於事件通信。

class JPjSipUaClickContact: publicJEventBody

SipUa按鍵類,封裝了界面的點擊撥號對象,用於事件通信。

class JPjSipUaCallStatus: public JEventBody

SipUa按鍵類,封裝了界面的呼叫狀態信息對象,用於事件通信。

class JPjSipUaContactList: publicJEventBody

SipUa通話列表類,封裝了界面的最近通話號碼列表對象,用於事件通信。

class JPjSipCallback: public JEventBody

SipUa回調函數類,在SIP協議棧線程的回調函數發送事件給SipUa線程時使用,用於事件通信。

class JPjSip: public JObject

Sip類,對PjSIP協議棧提供的用戶接口進行了封裝,提供更易用的C++接口,採用外觀模式。

class JPjSipUa: public JModule

SipUa類,負責SIP相關的所有操作,維護配置和內存數據,並調用Sip類完成SIP協議相關處理。


JLogSrv.cpp/h:

class JLogSrvCfg: public JEventBody

日誌服務器配置類,包含了日誌服務器類的配置,用於事件通信。

class JLogSrvNumber: public JEventBody

日誌服務器序號類,封裝了日誌服務器序號對象,用於事件通信。

class JLogSrvHasNewMsg: public JEventBody

日誌服務器信息提示類,封裝了日誌服務器消息提示對象,用於事件通信。

class JLogSrv: public JObject

日誌服務器類,負責日誌服務器相關的所有操作,維護配置和內存數據。日誌服務器線程類和日誌消息線程類操縱這個類完成實際的處理。

class JLogSrvThread: public JThread

日誌服務器線程類,負責日誌服務器事件的處理,爲避免與日誌消息收發的干擾採用獨立線程。

class JLogMsgThread: public JThread

日誌服務器消息類,爲每個日誌連接建立獨立線程來完成日誌信息的收發。


JLogSrvAgent.cpp/h:

class JLogServerAgent: public JObject

日誌服務器代理類,代表日誌服務器界面線程與組件框架線程進行通信,設置獲取相應的信息。


JPhoneAgent.cpp/h:

class JPhoneAgent: public JObject

軟電話代理類,代表軟電話界面線程與組件框架線程進行通信,設置獲取相應的信息。

(完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章