基于SOCK盯編程實(shí)現(xiàn)的組態(tài)軟件與控制器的網(wǎng)絡(luò)通訊
0 引言
組態(tài)軟件是面向工程監(jiān)控和數(shù)據(jù)采集的軟件平臺(tái)工具,具有豐富的設(shè)置項(xiàng)目。組態(tài)軟件所涉及的工業(yè)領(lǐng)域非常廣泛,在工業(yè)監(jiān)控系統(tǒng)中發(fā)揮著越來(lái)越重要的作用。組態(tài)軟件要接收現(xiàn)場(chǎng)的采集數(shù)據(jù),并形成動(dòng)態(tài)畫(huà)面,以反映工業(yè)現(xiàn)場(chǎng)的各種狀態(tài),并能夠?qū)ΜF(xiàn)場(chǎng)設(shè)備進(jìn)行控制。這些都依賴(lài)于組態(tài)軟件的通信模塊。通信模塊作為組態(tài)運(yùn)行環(huán)境中數(shù)據(jù)交互的重要渠道,通常處于監(jiān)控組態(tài)軟件運(yùn)行環(huán)境的核心區(qū),其功能直接決定著組態(tài)軟件的性能。本文在基于TCP/IP網(wǎng)絡(luò)協(xié)議和SOCKET接口技術(shù)的基礎(chǔ)上,介紹了基于IEC61131-3標(biāo)準(zhǔn)的組態(tài)軟件通訊模塊的設(shè)計(jì)與實(shí)現(xiàn)方法。
1 通信模塊功能
組態(tài)監(jiān)測(cè)系統(tǒng)分為控制器和工程師站兩部分,圖1所示是系統(tǒng)的總體結(jié)構(gòu)圖。圖中的控制器負(fù)責(zé)采集并處理數(shù)據(jù),工程師站負(fù)責(zé)接收控制器發(fā)送過(guò)來(lái)的數(shù)據(jù),并將數(shù)據(jù)顯示和保存。通信模塊根據(jù)用戶(hù)定義的通信協(xié)議實(shí)現(xiàn)工程師站組態(tài)軟件與控制器之間的數(shù)據(jù)通信,完成數(shù)據(jù)通信幀的組織下行和上行數(shù)據(jù)幀的校驗(yàn)、解析。由此可見(jiàn),在整個(gè)組態(tài)軟件中,通信功能模塊擔(dān)負(fù)著上層組態(tài)運(yùn)行環(huán)境與下層控制器之間數(shù)據(jù)交互的重要作用。
2 通信模塊設(shè)計(jì)
為了能夠及時(shí)、準(zhǔn)確的反映設(shè)備運(yùn)行狀況,設(shè)計(jì)時(shí)可采用基于TCP/IP協(xié)議的流式套接字(SOCK_STREAM)來(lái)實(shí)現(xiàn)組態(tài)軟件通信模塊的程序設(shè)計(jì)。
為了實(shí)現(xiàn)網(wǎng)絡(luò)通訊,Windows為應(yīng)用程序提供了各種編程接口,如Windows Sockets API等,應(yīng)用程序可以直接使用這些API函數(shù)。但對(duì)于較大型的應(yīng)用程序來(lái)說(shuō),應(yīng)該設(shè)計(jì)一個(gè)虛擬網(wǎng)絡(luò)接口層,以使能用windows提供的各種通訊API來(lái)為應(yīng)用程序提供通用的網(wǎng)絡(luò)功能。這樣的接口層可以采用中間DLL的形式,它將應(yīng)用程序和windows的各種API隔離開(kāi)來(lái),使程序員能更方便地設(shè)計(jì)自己的應(yīng)用程序。這樣的設(shè)計(jì)可使應(yīng)用程序更易于維護(hù)和移植。
基于通信需求和上述思路,利用基于TCP_IP的SOCKET接口可以實(shí)現(xiàn)網(wǎng)絡(luò)通信,通信模塊通常以動(dòng)態(tài)鏈接庫(kù)的形式存在。
2.1 Socket套接字
Windows Sockets不是一種網(wǎng)絡(luò)協(xié)議,而是一套開(kāi)放的、可支持多種協(xié)議的、Windows下的網(wǎng)絡(luò)編程接口。Winsock實(shí)際在計(jì)算機(jī)中提供了一個(gè)通信接口,應(yīng)用程序在網(wǎng)絡(luò)上傳輸信息都可以通過(guò)這個(gè)Socket接口來(lái)實(shí)現(xiàn)。Windows Sockets分為三種類(lèi)型:其中流式套接字(sock-stream)定義了一種可靠的面向連接的服務(wù),它使用TCP作為傳輸層協(xié)議,可實(shí)現(xiàn)無(wú)差錯(cuò)無(wú)重復(fù)地順序數(shù)據(jù)包傳輸;數(shù)據(jù)報(bào)套接字(sock-dgram)定義了一種無(wú)連接的服務(wù),它使用UDP協(xié)議,數(shù)據(jù)通過(guò)相互獨(dú)立的報(bào)文進(jìn)行傳輸,而且是無(wú)序的,同時(shí)不保證可靠和無(wú)差錯(cuò);原始套接字(sock-raw)允許對(duì)低層協(xié)議(如IP或ICMP)直接訪(fǎng)問(wèn),主要用于新網(wǎng)絡(luò)協(xié)議的實(shí)現(xiàn)和測(cè)試等。
圖2給出了一種典型的C/S(客戶(hù)端服務(wù)器)面向連接套接字調(diào)用的實(shí)現(xiàn)流程。
本系統(tǒng)中,工程師站組態(tài)軟件一般可作為客戶(hù)端向控制器發(fā)送連接請(qǐng)求,以建立連接。由于控制器采集數(shù)據(jù)是周期性的,組態(tài)軟件采用異步選擇機(jī)制判斷控制器是否有數(shù)據(jù)發(fā)送過(guò)來(lái)。Windows Sockets的異步選擇函數(shù)提供了消息機(jī)制的網(wǎng)絡(luò)事件選擇功能,當(dāng)它所登記的網(wǎng)絡(luò)事件發(fā)生時(shí),應(yīng)用程序相應(yīng)的窗口會(huì)收到一個(gè)消息,消息中指明了所發(fā)生的網(wǎng)絡(luò)事件以及與該網(wǎng)絡(luò)事件相關(guān)的一些信息。
連接建立之后,即可調(diào)用Winsock提供的函數(shù)來(lái)發(fā)送和接收數(shù)據(jù),進(jìn)程結(jié)束時(shí),則關(guān)閉兩個(gè)套接字。
2.2 數(shù)據(jù)交互
通訊模塊主要與框架、在線(xiàn)兩個(gè)模塊以及控制器存在數(shù)據(jù)交互。圖3所示是其通訊模塊與組態(tài)軟件的其它模塊及控制器之間進(jìn)行數(shù)據(jù)交互的流程圖。其中,通訊模塊發(fā)送給框架窗口的消息主要有三項(xiàng)功能:一是通知在線(xiàn)模塊讀取控制器返回的應(yīng)答數(shù)據(jù);二是在通訊中出現(xiàn)異常時(shí),返回錯(cuò)誤信息;三是在通訊出現(xiàn)超時(shí)時(shí),返回超時(shí)信息。
2.3 數(shù)據(jù)傳輸協(xié)議
TCP/IP協(xié)議族的核心部分是傳輸層和網(wǎng)絡(luò)層。傳輸層主要為應(yīng)用程序提供端到端的通信,TCP/IP協(xié)議族有兩個(gè)互不相同的傳輸協(xié)議,即TCP(傳輸控制協(xié)議)和UDP(用戶(hù)數(shù)據(jù)報(bào)協(xié)議)。
TCP是一種面向連接的協(xié)議,它可給用戶(hù)進(jìn)程提供可靠的全雙工的數(shù)據(jù)通信,其所做的工作是把應(yīng)用程序交給它的數(shù)據(jù)分成合適的小塊交給下面的網(wǎng)絡(luò)層,同時(shí)確認(rèn)接收到的分組,并提供流量控制、設(shè)定超時(shí)及重傳等機(jī)制。由于TCP提供有高可靠性的端到端的通信,因此,應(yīng)用程序可以忽略所有這些細(xì)節(jié)。
Winsock的Nagle算法會(huì)降低小數(shù)據(jù)包的發(fā)送速度,因此應(yīng)當(dāng)定義一種數(shù)據(jù)結(jié)構(gòu),以將發(fā)送的數(shù)據(jù)按照這種數(shù)據(jù)結(jié)構(gòu)以字符型ASCII發(fā)送,客戶(hù)端接收到服務(wù)器傳來(lái)的數(shù)據(jù),按照這種數(shù)據(jù)結(jié)構(gòu)解析數(shù)據(jù),這樣做可以減少小數(shù)據(jù)包的數(shù)目,避免協(xié)議使用Nagle算法。此外通過(guò)消息響應(yīng)代替輪詢(xún)也是提高傳輸實(shí)時(shí)性的一種措施。
2.4 阻塞的預(yù)防及處理
TCP/IP協(xié)議本身的滑動(dòng)窗口控制可以有效的防止阻塞的發(fā)生。假設(shè)服務(wù)器和客戶(hù)端的收發(fā)緩沖區(qū)大小為100 K字節(jié),服務(wù)器每發(fā)送一個(gè)大小為80 K字的數(shù)據(jù)包,客戶(hù)端接收到這個(gè)數(shù)據(jù)包后,將返回一個(gè)應(yīng)答,應(yīng)答中包含有下次服務(wù)器能夠發(fā)送的最大的字節(jié)數(shù),即下次服務(wù)器只能發(fā)送大小不能超過(guò)20 K字的數(shù)據(jù)。按照這種控制方法,TCP/IP可根據(jù)滑動(dòng)窗口的大小控制發(fā)送的速度,滑動(dòng)窗口大,則發(fā)送的數(shù)據(jù)量大,滑動(dòng)窗口過(guò)小,則發(fā)送的數(shù)據(jù)量也會(huì)減小,這樣即可以防止阻塞的發(fā)生。
該通訊模塊中使用的防阻塞方法是在同步方式中采用select函數(shù)來(lái)檢查接收發(fā)送緩沖區(qū)的讀寫(xiě)可用狀態(tài)。服務(wù)器端發(fā)送數(shù)據(jù)前,應(yīng)先檢查服務(wù)器的發(fā)送緩沖區(qū)是否可寫(xiě),如不可寫(xiě),說(shuō)明發(fā)送緩沖區(qū)己經(jīng)寫(xiě)滿(mǎn),需要等待發(fā)送緩沖區(qū)有剩余空間時(shí)再發(fā)送,以避免阻塞。同樣,客戶(hù)端在讀緩沖區(qū)數(shù)據(jù)前,也應(yīng)先檢查一下緩沖區(qū)是否可讀。如果發(fā)送緩沖區(qū)一直不可寫(xiě),那么可能是因?yàn)榫W(wǎng)絡(luò)斷開(kāi),或者網(wǎng)絡(luò)負(fù)載過(guò)大,使數(shù)據(jù)不能發(fā)送出去。
設(shè)置一個(gè)超時(shí)時(shí)限,可以阻塞發(fā)生時(shí),當(dāng)發(fā)送緩沖區(qū)不可寫(xiě)的狀態(tài)超過(guò)設(shè)置的超時(shí)時(shí)間,系統(tǒng)則重新建立一個(gè)連接。
將這種方法和TCP/IP協(xié)議本身的防阻塞控制結(jié)合使用,可以有效地防止阻塞的發(fā)生。
3 通信模塊的實(shí)現(xiàn)
3.1 實(shí)現(xiàn)思路
為了實(shí)現(xiàn)與控制器之間的異步通訊,通訊模塊的總體設(shè)計(jì)如圖4所示。
首先,由主線(xiàn)程調(diào)用外部接口函數(shù)以建立連接,同時(shí),創(chuàng)建發(fā)送和接收線(xiàn)程,以分別用于數(shù)據(jù)的發(fā)送和接收。
當(dāng)要發(fā)送數(shù)據(jù)時(shí),主線(xiàn)程調(diào)用外部接口函數(shù)來(lái)發(fā)送數(shù)據(jù)。該函數(shù)先將待發(fā)送的數(shù)據(jù)填充到通訊模塊的發(fā)送緩沖區(qū)中,然后通知發(fā)送線(xiàn)程,并由發(fā)送線(xiàn)程負(fù)責(zé)將發(fā)送緩沖區(qū)中的數(shù)據(jù)發(fā)送出去。
當(dāng)數(shù)據(jù)發(fā)送成功后,可由發(fā)送線(xiàn)程發(fā)送消息,通知接收線(xiàn)程準(zhǔn)備接收數(shù)據(jù)。
當(dāng)有應(yīng)答數(shù)據(jù)到來(lái)時(shí),接收線(xiàn)程將接收數(shù)據(jù)并將數(shù)據(jù)放入通訊模塊的接收緩沖區(qū)。接收完后,接收線(xiàn)程將發(fā)送消息以通知主線(xiàn)程讀取應(yīng)答數(shù)據(jù)。
主線(xiàn)程接到通知后,將調(diào)用外部接口函數(shù)接收數(shù)據(jù)。該函數(shù)可將通訊模塊的接收緩沖區(qū)中的應(yīng)答數(shù)據(jù)復(fù)制到應(yīng)用程序指定的緩沖區(qū)中。
數(shù)據(jù)的發(fā)送和接收交替進(jìn)行,就可以完成特定的操作。
3.2 模塊封裝
通過(guò)動(dòng)態(tài)鏈接庫(kù)技術(shù)可以提供一種方便、快捷的資源共享途徑。這實(shí)質(zhì)上是一些函數(shù)、數(shù)據(jù)和類(lèi)集合成的可執(zhí)行模塊。通信模塊采用動(dòng)態(tài)鏈接庫(kù)形式,可以在實(shí)現(xiàn)同一臺(tái)機(jī)器上的多個(gè)工程師站組態(tài)軟件進(jìn)程的同時(shí)與多個(gè)控制器進(jìn)行通訊。
將通信模塊中套接字的建立、端口的綁定、數(shù)據(jù)的接收和發(fā)送封裝到動(dòng)態(tài)鏈接庫(kù)中,同時(shí)屏蔽一些操作細(xì)節(jié),這樣的方法可以方便地被其它程序所調(diào)用,更易于程序維護(hù)和移值,也方便將來(lái)程序的升級(jí)。
根據(jù)窗口句柄發(fā)送消息至該窗口,然后通知應(yīng)用程序有數(shù)據(jù)到達(dá)。最后,還需要在函數(shù)前面使用extern“C”_declspec(dllexport)關(guān)鍵字,以使該P(yáng)EI數(shù)能夠被其它程序所調(diào)用。函數(shù)的參數(shù)分別為端口號(hào)和應(yīng)用程序的句柄。在應(yīng)用程序中,只需要調(diào)用該函數(shù),就可以開(kāi)啟TCP/IP服務(wù)。按照同樣的方法,也可以封裝連接服務(wù)函數(shù)和發(fā)送數(shù)據(jù)函數(shù)。組態(tài)軟件的在線(xiàn)等模塊通過(guò)調(diào)用這些導(dǎo)出函數(shù),就可以完成與控制器的通訊,而不用考慮具體的通訊細(xì)節(jié)。具體的通訊細(xì)節(jié)可在這些導(dǎo)出函數(shù)中實(shí)現(xiàn)。
4 結(jié)束語(yǔ)
在基于TCP/IP協(xié)議網(wǎng)絡(luò)通訊的基礎(chǔ)上,針對(duì)狀態(tài)監(jiān)測(cè)中數(shù)據(jù)傳輸?shù)拈g歇這一特殊性,提出了一種基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)通訊模塊的設(shè)計(jì)方法,并將這種方法封裝到動(dòng)態(tài)鏈接庫(kù)中,然后通過(guò)函數(shù)接口與應(yīng)用程序交互。由于該通訊模塊是以動(dòng)態(tài)鏈接庫(kù)形式給出的,編程者可以不需要深入了解TCP/IP協(xié)議以及Socket高級(jí)編程,而中需簡(jiǎn)單地調(diào)用通訊模塊中的函數(shù),即可實(shí)現(xiàn)局域網(wǎng)中數(shù)據(jù)的傳輸。本文所介紹的通信模塊的設(shè)計(jì)方法目前已經(jīng)實(shí)現(xiàn),其可行性也得到了驗(yàn)證,并已應(yīng)用在實(shí)際的組態(tài)軟件開(kāi)發(fā)項(xiàng)目中。