系統(tǒng)的實(shí)現(xiàn)基于如下開發(fā)環(huán)境,如表1所示。
客戶端主要由連接模塊、數(shù)據(jù)庫模塊、任務(wù)管理模塊、狀態(tài)信息模塊、預(yù)覽模塊、錯(cuò)誤處理模塊等組成。其中,客戶端自動(dòng)重連機(jī)制的實(shí)現(xiàn)是非常關(guān)鍵的,系統(tǒng)設(shè)計(jì)了兩種情況將調(diào)用該機(jī)制:第一是客戶端啟動(dòng)時(shí),第二是網(wǎng)絡(luò)出現(xiàn)問題時(shí)。
(1)查詢數(shù)據(jù)庫,檢查是否有未完成任,如果沒有直接進(jìn)行第(4)步;
(2)如果有未完成任務(wù),將任務(wù)加入任務(wù)管理隊(duì)列;
(3)處理未完成任務(wù),利用任務(wù)信息,向服務(wù)器端發(fā)送重連請(qǐng)求(RegUnfiCMD);根據(jù)任務(wù)對(duì)應(yīng)的服務(wù)器IP地址,分別與對(duì)應(yīng)服務(wù)器建立連接;值得注意的是,每個(gè)客戶端與每個(gè)服務(wù)器之間只有一條通道。發(fā)往同一服務(wù)器的后續(xù)任務(wù)直接利用已用通道,發(fā)送更新信息。
表1 開發(fā)環(huán)境
(4)啟動(dòng)客戶端。
(1)客戶端在1分鐘后,查詢數(shù)據(jù)庫,讀取未完成任務(wù),如果沒有,等待新的任務(wù);
(2)如果有未完成任務(wù),將任務(wù)加入任務(wù)管理隊(duì)列;
(3)處理未完成任務(wù),從新與服務(wù)器進(jìn)行連接請(qǐng)求,后續(xù)隊(duì)列的任務(wù)做相同的操作,但如果服務(wù)器與客戶端已經(jīng)建立連接,后續(xù)任務(wù)不需要再發(fā)送建立連接請(qǐng)求;如果不能建立連接,轉(zhuǎn)到第(1)步。
當(dāng)客戶端啟動(dòng)時(shí)自動(dòng)重連對(duì)應(yīng)的偽代碼如下:
當(dāng)服務(wù)器與客戶端網(wǎng)絡(luò)斷開后,調(diào)用定時(shí)器SetTimer(10,60000,NULL),則OnTimer(UINT nIDEvent)就會(huì)在1分鐘后激活進(jìn)行重連請(qǐng)求。OnTimer實(shí)際上調(diào)用了客戶端啟動(dòng)時(shí)的處理機(jī)制。由于系統(tǒng)是多對(duì)多模式,因此在服務(wù)器與客戶端網(wǎng)絡(luò)斷開后,客戶端與其他服務(wù)器的連接不會(huì)影響,只是處理斷開的服務(wù)器重連。
由于本系統(tǒng)采用基于安全通道的網(wǎng)絡(luò)機(jī)制,故實(shí)現(xiàn)客戶端連接模塊的代碼利用OpenSSL。
當(dāng)有任務(wù)要上傳的時(shí)候,首先需要選擇可信的服務(wù)器,然后通過三次握手建立連接。
下面是對(duì)應(yīng)的偽代碼:
只有通信雙方具有可信的證書,才能建立起連接。這樣就確保了通信雙方能夠在安全狀態(tài)下進(jìn)行數(shù)據(jù)傳輸。
數(shù)據(jù)庫模塊是客戶端合理工作的保證,涉及任務(wù)管理、任務(wù)插入、任務(wù)查詢和任務(wù)刪除等。本系統(tǒng)利用開源ado2類對(duì)ACEESS數(shù)據(jù)庫進(jìn)行讀寫操作。設(shè)計(jì)對(duì)數(shù)據(jù)操作的CDatebaseMannager類,該類涉及如下函數(shù):
int OpenDatabase();打開數(shù)據(jù)庫
int CloseDatabase();關(guān)閉數(shù)據(jù)庫
int SelectSQL(CString strSQLCommand);查詢數(shù)據(jù)庫
int InsertSQL(CString strSQLCommand);插入數(shù)據(jù)庫
int UpdateSQL(CString strSQLCommand);更新數(shù)據(jù)庫
int DeleteSQL(CString strSQLCommand);刪除數(shù)據(jù)庫
int ExecuteProc(CStri ng strSQLCommand); 執(zhí)行SQL語句
任務(wù)管理模塊主要負(fù)責(zé)任務(wù)的調(diào)度、任務(wù)上傳以及與服務(wù)器間的通信,是整個(gè)客戶端系統(tǒng)的靈魂。
實(shí)現(xiàn)的函數(shù)為handleUploadCmd,該函數(shù)是整個(gè)系統(tǒng)運(yùn)行的保證,在函數(shù)內(nèi)部設(shè)計(jì)任務(wù)文件的上傳、文件的壓縮以及文件狀態(tài)管理。
圖像預(yù)覽模塊利用CxImage類,可以對(duì)各類文件進(jìn)行預(yù)覽,即任務(wù)文件在上傳之前,用戶可以對(duì)起預(yù)覽。
同 時(shí), 可 以 設(shè) 計(jì)CPictrueView類對(duì)預(yù)覽文件進(jìn)行放大、縮小等操作。
OpenTifFile函數(shù)負(fù)責(zé)對(duì)傳輸文件讀取預(yù)覽。
與此同時(shí),系統(tǒng)還提供了GetFirstBitmapFromAvi函數(shù),實(shí)現(xiàn)獲取并預(yù)覽avi文件第一幀圖像的功能。
類CStateShowDlg是狀態(tài)信息模塊,用于把任務(wù)實(shí)際運(yùn)行狀態(tài)反饋給用戶,通過與任務(wù)管理模塊相結(jié)合,實(shí)時(shí)反映任務(wù)狀態(tài)。
其偽代碼如下:
更加詳細(xì)的任務(wù)狀態(tài)信息是基于任務(wù)內(nèi)部的單個(gè)文件,系統(tǒng)中定義了如下結(jié)構(gòu)體用于管理文 件 :FileUploadInfo、CurrentUploadStatus、UploadFileStatus等。除此之外,客戶端還有以下幾個(gè)類:CClientDlg是整個(gè)系統(tǒng)的框架;CDutyInitDlg主要負(fù)責(zé)任務(wù)初始化。
與數(shù)據(jù)庫通信部分的實(shí)現(xiàn),主要涉及到部門信息的編輯、歷史任務(wù)的查詢以及任務(wù)對(duì)應(yīng)文件的查詢。其過程如下:
第一,是部門信息的編輯,這部分主要是提供數(shù)據(jù)庫接口,方便添加、刪除、修改部門信息。
增加部門信息的實(shí)現(xiàn)函數(shù)為AddClinicInfoRecord函數(shù),具體實(shí)現(xiàn)為:
同樣有關(guān)修改部門信息的實(shí)現(xiàn)為ModifyClinicInfoRecord函數(shù),其具體實(shí)現(xiàn)方式,如圖1所示。
圖1 修改函數(shù)的具體實(shí)現(xiàn)
第二,是歷史任務(wù)查詢,通過給定的起止時(shí)間、查詢數(shù)據(jù)庫、返回所有滿足條件的人物信息,核心查詢函數(shù)為OnCheck函數(shù),實(shí)現(xiàn)代碼如圖2所示。
第三,查詢?nèi)蝿?wù)對(duì)應(yīng)文件信息主要對(duì)應(yīng)兩個(gè)位置:其一是查詢歷史任務(wù)時(shí),支持返回每個(gè)任務(wù)對(duì)應(yīng)的文件;其二是任務(wù)狀態(tài)欄中任務(wù)對(duì)應(yīng)的文件查詢功能。SQLFILE函數(shù)實(shí)現(xiàn)形式如圖3所示。
圖2 歷史任務(wù)查詢的具體實(shí)現(xiàn)
圖3 SQLFILE函數(shù)實(shí)現(xiàn)形式
服務(wù)器端主要實(shí)現(xiàn)如下模塊:啟動(dòng)模塊、客戶端連接請(qǐng)求模塊、數(shù)據(jù)庫管理模塊、客戶端管理模塊、任務(wù)管理模塊、任務(wù)狀態(tài)及預(yù)覽模塊、任務(wù)接收模塊、文件解壓模塊。
啟動(dòng)模塊是主要完成服務(wù)器啟動(dòng),打開監(jiān)聽端口,同樣利用OpenSSL開放源碼。服務(wù)器啟動(dòng)時(shí),AfxBeginThr ead(ServerThread,this)實(shí)現(xiàn)網(wǎng)絡(luò)初始化,偽代碼如下:
服務(wù)器端數(shù)據(jù)庫管理模塊類似與客戶端,同樣也利用設(shè)計(jì)的CDatebaseMannager類 對(duì)ACCESS數(shù)據(jù)庫進(jìn)行讀寫操作。服務(wù)器啟動(dòng)時(shí),同樣需要讀取未完成任務(wù),并加入任務(wù)管理隊(duì)列,并等待客戶端發(fā)續(xù)傳請(qǐng)求進(jìn)行激活。
客戶端管理模塊與任務(wù)管理模塊是服務(wù)器系統(tǒng)管理的主要對(duì)象。建立不同的數(shù)據(jù)結(jié)構(gòu)進(jìn)行管理。ListManagement用于任務(wù)管理,而ListServer用于管理客戶端。所有的待完成任務(wù)都由ListManagement進(jìn)行管理,每個(gè)SSL對(duì)應(yīng)一個(gè)客戶端IP地址。
任務(wù)狀態(tài)模塊,它同客戶端一樣。
客戶端先發(fā)起服務(wù)器請(qǐng)求,并與服務(wù)器建立SSL連接后,就可以與服務(wù)器進(jìn)行通信。
發(fā)送新任務(wù)注冊(cè)SendDutyReg(SSL*ssl),更新未完成任務(wù)SendRegUnfinish(SSL* ssl,DutyInfo* dutyinfo)。對(duì)應(yīng)接收服務(wù)器通信函數(shù)為HandleData(SSL * ssl),getNextUploadItem()函數(shù)在客戶端與服務(wù)器建立連接后,就持續(xù)工作,負(fù)責(zé)任務(wù)上傳的同步。
handleUploadCmd(char*m_pRecvData,SSL *ssl,int uploadflag)函數(shù)實(shí)現(xiàn)任務(wù)上傳,該函數(shù)中涉及文件壓縮、狀態(tài)信息反饋、任務(wù)調(diào)度等。
一個(gè)任務(wù)實(shí)際上由一個(gè)或多個(gè)文件組成,因此任務(wù)上傳主要完成對(duì)文件的上傳。
任務(wù)上傳的狀態(tài)見表2所示,這些狀態(tài)同時(shí)也會(huì)反饋給客戶端用戶。
服務(wù)器與客戶端通信實(shí)現(xiàn):服務(wù)器根據(jù)任務(wù)隊(duì)列,調(diào)用getNextUploadItem函數(shù),發(fā)送針對(duì)某個(gè)任務(wù)的UploadCMD請(qǐng)求給客戶端??蛻舳薍andleData函數(shù)接收到UploadCMD命令,調(diào)用handleUploadCmd處理該任務(wù)對(duì)應(yīng)文件的上傳。
表2 任務(wù)上傳狀態(tài)