高志國,李巧鴿,高新鵬
(1.中原油田勘察設計研究院,河南濮陽 457001;2.中石化銷售華北分公司河南輸油管理處,鄭州 450015)
中原油田天然氣處理廠主要針對油田天然氣進行深冷加工處理,天然氣處理量1.2×106m3/d。由于該廠廠區(qū)范圍大,生產(chǎn)車間多且分散,按照中石化安全生產(chǎn)的統(tǒng)一要求,在各關鍵生產(chǎn)點安裝了視頻監(jiān)控系統(tǒng),并將數(shù)據(jù)遠傳至生產(chǎn)調(diào)度室監(jiān)控中心。監(jiān)控系統(tǒng)包括本地和遠程監(jiān)控兩部分。在遠程監(jiān)控中心和現(xiàn)場監(jiān)控之間通過局域網(wǎng)絡連接。遠程監(jiān)控中心可以任意對各個現(xiàn)場實行監(jiān)控,既可以完成對現(xiàn)場視頻圖像數(shù)據(jù)的實時接收、解壓縮、播放、存儲以及控制該現(xiàn)場的攝像機切換,鏡頭、云臺動作,又可以接收處理現(xiàn)場的報警信息。
遠程監(jiān)控中心監(jiān)控程序的設計主要涉及數(shù)據(jù)收發(fā)、分析處理及顯示等模塊。數(shù)據(jù)收發(fā)是控制臺程序的重要部分,如果沒有合理有效的收發(fā)模塊設計方案,將影響到其他模塊的正常運轉。為了提高監(jiān)控中心的運行效率,確保通信快速有效地進行,將數(shù)據(jù)收發(fā)模塊做成了一個獨立的基于Win32的控制臺程序,采用了 Win32多線程編程技術和Socket網(wǎng)絡編程技術。
在網(wǎng)絡通信中最常用的協(xié)議是 TCP/IP協(xié)議簇。它已成為現(xiàn)代工廠生產(chǎn)網(wǎng)絡的工業(yè)標準。Socket(套接字)最早是Unix系統(tǒng)中采用 TCP/IP協(xié)議簇而提供的網(wǎng)絡通信接口,隨著計算機操作系統(tǒng)的發(fā)展,Windows操作系統(tǒng)也采用了Socket,提供了 Window API供開發(fā)人員調(diào)用。Windows Socket(簡稱 WinSock)編程接口是 Windows環(huán)境下最廣泛使用的網(wǎng)絡編程接口。
視頻監(jiān)控系統(tǒng)程序設計如圖1所示。在服務器端分為2個功能模塊:通信模塊——數(shù)據(jù)收發(fā)程序;數(shù)據(jù)處理模塊——監(jiān)控中心控制臺。遠程監(jiān)控中心服務器運行兩個程序,數(shù)據(jù)收發(fā)程序和監(jiān)控中心控制臺。
圖1 視頻監(jiān)控系統(tǒng)基本結構
數(shù)據(jù)收發(fā)程序主要有三個功能:與遠程服務器端通信;與控制臺通信;操作數(shù)據(jù)庫。與控制臺數(shù)據(jù)通信主要是利用 Windows消息進行的,利用ADO技術實現(xiàn)數(shù)據(jù)采集器對數(shù)據(jù)庫的操作;與遠程服務器通信采用Socket編程技術。如何有效地與遠程服務器端進行通信并將得到的數(shù)據(jù)有效地寫入數(shù)據(jù)庫,保證數(shù)據(jù)不丟失并傳送到控制臺是設計的核心和難點。
數(shù)據(jù)收發(fā)程序的線程設計如下:
a)主線程。初始化用于進行同步的事件變量,臨界區(qū)變量,共享資源等,并建立一個偵聽套接字,負責為新的服務器連接請求開啟線程,建立傳輸套接字。當主線程收到結束程序的信號時將為各個線程發(fā)出終止事件,等待各個線程的終止,并釋放資源。
b)遠程控制線程。用來負責向遠程服務器端發(fā)送控制命令。
c)遠程監(jiān)視進程。用來負責監(jiān)視所有遠程服務器端的運行狀況以及網(wǎng)絡狀況,從而實現(xiàn)在控制中心實時顯示服務器端的運行狀態(tài)。
d)數(shù)據(jù)傳輸線程。該線程的數(shù)目與遠程現(xiàn)場服務器端的數(shù)目相同,對應進行處理各個服務器發(fā)來的數(shù)據(jù),將接收到的視頻流信息和報警信息入庫,并將接收到的數(shù)據(jù)發(fā)送給控制臺進行數(shù)據(jù)分析處理。
e)數(shù)據(jù)傳輸維護線程。將數(shù)據(jù)傳輸線程做一個鏈表,實時維護此鏈表中各個線程的有效性(負責記錄存在的線程,刪除終止的線程并釋放其資源,增加新建的線程)。該線程是為了解決數(shù)據(jù)傳輸線程復雜不易管理的問題,使得每一個線程都能夠正常運行。成功解決了實際應用中曾經(jīng)存在的啟動多個線程的問題。具體執(zhí)行過程如圖2所示。
圖2 數(shù)據(jù)收發(fā)模塊流程
2.3.1 定義的數(shù)據(jù)結構和重要的全局變量
首先定義了一個用于描述每一個服務器端信息的數(shù)據(jù)結構 ClientInfo和一個服務器鏈表ClientList,分別如下所示:
數(shù)據(jù)結構ClientInfo不但記錄了服務器的基本信息(如服務器端 IP),還記錄了與該服務器端通信所對應的套接字標識sd和用于接收處理該服務器視頻流的線程標識 ThreadID,目的是為了在程序運行過程中可以有效地控制系統(tǒng)的線程和套接字的開關情況。字段send_time和rec_time字段主要是用來察看遠程服務器端運行狀態(tài)用的。當rec_time或send_time與當前時間超過一定間隔時需要重新向服務器端發(fā)送狀態(tài)請求數(shù)據(jù)包以檢測其運行狀態(tài)。ClientList是以ClientInfo為節(jié)點的鏈表結構。g_ci_list是系統(tǒng)定義的一個ClientList的全局指針變量,用來指向保存與控制中心正常連接的遠程現(xiàn)場服務器列表。
另外定義的一個數(shù)據(jù)結構NewClientInfor和一個全局變量g_nci用來保存新連接請求的服務器端的基本信息。定義如下:typedef struct_ NewClientInfor{
2.3.2 線程的啟動
創(chuàng)建一個新的線程是使用 WinAPI函數(shù)CreateThread。該函數(shù)的系統(tǒng)聲明如下:
每一個線程定義其實現(xiàn)函數(shù)之后,通過在主線程中調(diào)用Creat Thread函數(shù)即開啟了該線程。
2.3.3 網(wǎng)絡通信的實現(xiàn)
對遠程服務器數(shù)據(jù)的發(fā)送接收采用的是TCP套接字。由于多個線程和現(xiàn)場服務器端通信時用到同一個套接字,為了有效地對套接字進行使用,將其設定為非阻塞模式(Nonblocking),采用Select模型,利用 select函數(shù),判斷套接字上是否存在數(shù)據(jù),或者能否向一個套接字寫入數(shù)據(jù)。具體實現(xiàn)如下:
該方案利用多線程和套接字技術成功地解決了遠程控制中心對多個現(xiàn)場監(jiān)視的數(shù)據(jù)收發(fā)任務。該方案也適合類似于服務器和多服務器進行數(shù)據(jù)采集和控制的任何模型。線程間同步以及線程生存期內(nèi)的維護是多線程編程應該注意的關鍵問題。由于多個線程同時需要對同一個套接字的使用,使用了非阻塞套接字模式和select模型,避免了在套接字處于非鎖定模式中時,產(chǎn)生WSAEWOULDBLOCK錯誤。
[1] 劉富強.數(shù)字視頻監(jiān)控系統(tǒng)開發(fā)及應用[M].北京:機械工業(yè)出版社,2003.
[2] J EFFREY R.Windows高級編程指南[M].王書洪,劉光明譯.北京:清華大學出版社,1999.
[3] ANTHONYJ.Windows網(wǎng)絡編程技術[M].京京工作室譯.北京:機械工業(yè)出版社,2000.
[4] 黃杰生.結合消息隊列機制的多線程TCP通信開發(fā)平臺[J].計算機應用研究,2004,(5):247-249.
[5] 李納瑩.利用MFC多線程技術開發(fā)基于UDP數(shù)據(jù)廣播的局域網(wǎng)絡會議程序[J].電腦編程技巧與維護,2004,(2):24.
[6] 蔡翠平,宋曉霞,蘇學濤.多媒體計算機網(wǎng)絡通信技術應用[M].北京:北京大學出版社,2007.
[7] 劉直芳,王運瓊.數(shù)字圖象處理與分析[M].北京:清華大學出版社,2006.