張浩然+耿戰(zhàn)霞+鹿海成
摘 要:為滿足跨正向隔離裝置傳輸文件的需求,設(shè)計(jì)了一種文件傳輸協(xié)議,制定了報(bào)文格式及工作機(jī)制,給出了發(fā)送端和接收端的狀態(tài)遷移過(guò)程。然后基于C++語(yǔ)言/Qt框架,實(shí)現(xiàn)了發(fā)送端和接收端的編程。該協(xié)議設(shè)計(jì)簡(jiǎn)單、易于實(shí)現(xiàn),便于擴(kuò)展,具有一定的通用性。
關(guān)鍵詞:正向隔離裝置;文件傳輸協(xié)議;設(shè)計(jì);實(shí)現(xiàn)
中圖分類號(hào):TM769 文獻(xiàn)標(biāo)志碼:A 文章編號(hào):2095-2945(2017)24-0101-03
引言
為保障電力信息網(wǎng)絡(luò)的安全性,電力系統(tǒng)根據(jù)安全等級(jí)把信息網(wǎng)絡(luò)劃分為I、Ⅱ、Ⅲ等區(qū)。I/Ⅱ區(qū)向Ⅲ區(qū)傳遞數(shù)據(jù)要求有正向隔離裝置做隔離。
網(wǎng)絡(luò)隔離技術(shù)在確保保障電力信息網(wǎng)絡(luò)安全的同時(shí),也給信息的跨區(qū)通信帶來(lái)了不便。本文設(shè)計(jì)了一個(gè)可透過(guò)正向隔離裝置的文件傳輸協(xié)議,據(jù)此實(shí)現(xiàn)的文件傳輸系統(tǒng)系統(tǒng),為I/Ⅱ區(qū)向Ⅲ區(qū)的數(shù)據(jù)傳輸提供了很好的支持。
1 正向隔離裝置工作原理
正向隔離裝置主要功能體現(xiàn)在禁止兩個(gè)區(qū)域的應(yīng)用之間直接建立TCP連接。它將兩個(gè)區(qū)域的應(yīng)用之間的TCP連接分解成兩個(gè)區(qū)域的應(yīng)用各自到隔離裝置內(nèi)外兩個(gè)網(wǎng)卡的兩個(gè)TCP虛擬連接。隔離裝置內(nèi)外兩個(gè)網(wǎng)卡在裝置內(nèi)部為非網(wǎng)絡(luò)連接。正向隔離裝置工的作模式如圖1所示。
正向隔離裝置只允許表示層與應(yīng)用層數(shù)據(jù)單向傳輸,即從安全區(qū)III到安全區(qū)I/II的應(yīng)答報(bào)文禁止攜帶應(yīng)用數(shù)據(jù)(最多只能通過(guò)一個(gè)字節(jié)的數(shù)據(jù),而且要么全為0,要么全為1)。
電力二次系統(tǒng)I/Ⅱ區(qū)與Ⅲ區(qū)增設(shè)正向隔離裝置后,普通的C/S和B/S程序無(wú)法穿越該裝置,需按隔離裝置編程規(guī)定修改程序,才能進(jìn)行數(shù)據(jù)通信。
這使得常規(guī)網(wǎng)絡(luò)中容易解決的問(wèn)題,變得復(fù)雜了。如Ⅲ區(qū)的應(yīng)用想要獲得I/Ⅱ區(qū)的文件,常見(jiàn)的文件共享方法如FTP服務(wù)、共享文件夾等都無(wú)法使用。需使用專門的跨正向隔離裝置的文件傳輸系統(tǒng)。雖然正向隔離裝置的生產(chǎn)商都提供了基于Java的文件透?jìng)飨到y(tǒng),但并非所有的設(shè)備都能運(yùn)行Java程序,特別是資源緊張的嵌入式設(shè)備。而若部署專門的文件傳輸服務(wù)器,又增加了成本。因此,有必要自行開(kāi)發(fā)跨正向隔離裝置的文件傳輸系統(tǒng)。
2 文件傳輸協(xié)議
現(xiàn)有的FTP等文件傳輸協(xié)議都需發(fā)送端和接收端交互大量的控制報(bào)文,以對(duì)數(shù)據(jù)的發(fā)送、接收、重傳等進(jìn)行控制。而正向隔離裝置禁止從Ⅲ區(qū)到I/Ⅱ區(qū)的報(bào)文攜帶應(yīng)用數(shù)據(jù)。這使得現(xiàn)有協(xié)議都無(wú)法使用。因此,本文設(shè)計(jì)了一種新的文件傳輸協(xié)議FTPAFID(跨正向隔離裝置文件傳輸協(xié)議,F(xiàn)ile Transfer Protocol Across Forward Isolating Device)以適應(yīng)跨正向隔離裝置傳輸文件的需要。
2.1 報(bào)文格式
FTPAFID共定義了三種報(bào)文。其中數(shù)據(jù)報(bào)文和?;顖?bào)文由發(fā)送端產(chǎn)生,確認(rèn)報(bào)文由接收端產(chǎn)生。
數(shù)據(jù)報(bào)文用于傳送文件。第一個(gè)字段(1Byte)表示類型碼;第二個(gè)字段(2Byte)表示數(shù)據(jù)長(zhǎng)度;從第三個(gè)字段開(kāi)始到報(bào)文末為數(shù)據(jù)段。數(shù)據(jù)報(bào)文共定義了三種操作碼:文件名稱(值為0x01),文件內(nèi)容(值為0x02)和文件hash字符串(值為0x03)。
?;顖?bào)文用于在不傳送文件時(shí)檢測(cè)通信狀態(tài)。保活報(bào)文為一個(gè)字節(jié),字節(jié)數(shù)值為0x0f。
確認(rèn)報(bào)文為一個(gè)字節(jié),用于確認(rèn)接收到的報(bào)文。其值為0xff時(shí)表示收到的報(bào)文正確,而值為0x00時(shí)表示收到的報(bào)文錯(cuò)誤或收到的文件校驗(yàn)錯(cuò)誤。
具體的報(bào)文結(jié)構(gòu)如圖2所示。
2.2 工作模式
FTPAFID協(xié)議被設(shè)計(jì)為一種停止等待協(xié)議,采用一問(wèn)一答方式工作。圖3顯示了FTPAFID協(xié)議在傳輸文件時(shí),正常情況發(fā)送端和接收端的交互過(guò)程。
以傳輸一個(gè)文件為例,在開(kāi)始工作時(shí),F(xiàn)TPAFID的發(fā)送端首先發(fā)送一個(gè)文件名報(bào)文給接收端。接收端收到報(bào)文后返回一個(gè)OK報(bào)文。發(fā)送端在收到確認(rèn)報(bào)文后發(fā)送一個(gè)文件數(shù)據(jù)報(bào)文。接收端收到數(shù)據(jù)報(bào)文后返回一個(gè)OK報(bào)文。重復(fù)這個(gè)過(guò)程直到文件傳送完。最后一個(gè)數(shù)據(jù)報(bào)文的數(shù)據(jù)長(zhǎng)度字段的數(shù)值為0。當(dāng)接收端收到數(shù)據(jù)長(zhǎng)度字段數(shù)值為0的數(shù)據(jù)報(bào)文時(shí),就知道文件數(shù)據(jù)傳輸結(jié)束。最后發(fā)送端會(huì)發(fā)送一個(gè)文件hash字符串報(bào)文。接收端在接收完文件后,會(huì)計(jì)算文件的hash字符串,并與收到的hash字符串進(jìn)行對(duì)比,如兩者一致,就返回OK報(bào)文。
2.3 ?;罟δ芎筒铄e(cuò)控制
FTPAFID協(xié)議的收/發(fā)兩端在工作時(shí)需經(jīng)過(guò)一個(gè)正向隔離裝置中轉(zhuǎn),因此無(wú)法基于TCP協(xié)議提供的控制功能判斷通信是否中斷,必須自己進(jìn)行控制。
FTPAFID的?;罟δ茉O(shè)計(jì)為:在空閑時(shí)由發(fā)送端定時(shí)向接收端發(fā)送保活報(bào)文,接收端收到報(bào)文后返回確認(rèn)報(bào)文;當(dāng)發(fā)送端超時(shí)未收到確認(rèn)報(bào)文或接收端超時(shí)未收到保活報(bào)文時(shí),判定通信為中斷狀態(tài)。
?;罟δ軐?duì)接收端尤其重要。若沒(méi)有?;罟δ?,接收端無(wú)法判斷通道上沒(méi)有數(shù)據(jù)是因?yàn)闆](méi)有文件需要傳送,還是發(fā)送端已經(jīng)崩潰。如果發(fā)送端已崩潰,使得在接收端上留下一個(gè)開(kāi)放連接,而接收端又在等待發(fā)送端的數(shù)據(jù),則發(fā)送端將永遠(yuǎn)等待下去。
因?yàn)檎蚋綦x裝置只允許接收端返回0xff和0x00兩種報(bào)文,無(wú)法表示太多含義,所以FTPAFID的差錯(cuò)控制實(shí)現(xiàn)的很簡(jiǎn)單。無(wú)論是在傳送文件還是在空閑狀態(tài),發(fā)送端在超時(shí)未收到確認(rèn)報(bào)文或收到的確認(rèn)報(bào)文為0x00時(shí)都直接關(guān)閉通道。接收端在超時(shí)未收到報(bào)文時(shí)直接關(guān)閉通道;而在文件傳輸過(guò)程中收到錯(cuò)誤報(bào)文或文件傳輸完畢后文件校驗(yàn)錯(cuò)誤時(shí),先返回值為0x00的ERR報(bào)文,然后關(guān)閉通道。
2.4 發(fā)送端狀態(tài)變遷
FTPAFID發(fā)送端首先向接收端(實(shí)際是隔離裝置)發(fā)起連接請(qǐng)求,建立連接。建立連接后,發(fā)送端處于空閑狀態(tài)。如果無(wú)文件需要發(fā)送,則定時(shí)發(fā)送?;顖?bào)文,以確認(rèn)接收端工作正常。若有文件需要發(fā)送,則先發(fā)送文件名稱報(bào)文;收到確認(rèn)后繼續(xù)發(fā)送文件內(nèi)容報(bào)文;按照發(fā)送/確認(rèn)機(jī)制持續(xù)發(fā)送文件內(nèi)容報(bào)文直到文件內(nèi)容完全傳送完畢;最后,發(fā)送端會(huì)發(fā)送文件hash報(bào)文,收到確認(rèn)后完成整個(gè)文件的傳送并返回空閑狀態(tài)。接收端在發(fā)送任何報(bào)文后,如果超時(shí)未收到確認(rèn)報(bào)文或收到ERR報(bào)文,都會(huì)關(guān)閉連接停止運(yùn)行。這些工作流程都能從圖4所示的發(fā)送端狀態(tài)變遷圖中得出。endprint
2.5 接收端狀態(tài)變遷
FTPAFID接收端接收發(fā)送端(實(shí)際是隔離裝置)發(fā)起的連接請(qǐng)求并建立連接,隨后進(jìn)入空閑狀態(tài)。此時(shí),接收端會(huì)等待發(fā)送端傳送來(lái)的報(bào)文。如收到?;顖?bào)文,接收端會(huì)發(fā)送OK報(bào)文,并繼續(xù)等待。如收到文件名稱報(bào)文,則在發(fā)送OK報(bào)文后,進(jìn)入等待文件內(nèi)容狀態(tài)。接收端持續(xù)接收文件內(nèi)容報(bào)文,直至收到數(shù)據(jù)長(zhǎng)度為0的文件內(nèi)容報(bào)文。此時(shí),接收端判定文件內(nèi)容已全部傳送完畢,進(jìn)入等待文件hash狀態(tài)。接收端收到文件hash報(bào)文并校驗(yàn)無(wú)誤后,發(fā)送OK確認(rèn)報(bào)文,進(jìn)入空閑等待狀態(tài)。接收端在等待任何報(bào)文的狀態(tài)下,如果超時(shí)未收到報(bào)文,都會(huì)直接關(guān)閉連接;如果收到的報(bào)文無(wú)法識(shí)別,接收端會(huì)先回復(fù)一個(gè)ERR報(bào)文,然后關(guān)閉連接停止運(yùn)行。圖5所示為FTPAFID接收端的工作狀態(tài)變遷。
3 協(xié)議實(shí)現(xiàn)
基于FTPAFID協(xié)議開(kāi)發(fā)的跨正向隔離裝置文件傳輸系統(tǒng)已成功應(yīng)用于許繼直流輸電系統(tǒng)故障分析處理輔助決策平臺(tái)。整個(gè)文件傳輸系統(tǒng)基于C++語(yǔ)言/Qt框架實(shí)現(xiàn),可分為發(fā)送軟件和接收軟件兩部分,分別部署在正向隔離裝置的兩側(cè)。
3.1 發(fā)送端實(shí)現(xiàn)
發(fā)送軟件的發(fā)送器類負(fù)責(zé)具體的文件傳輸過(guò)程,它實(shí)現(xiàn)了FTPAFID的發(fā)送端部分。發(fā)送器結(jié)構(gòu)如圖6所示。
發(fā)送器內(nèi)部持有一個(gè)QTcpSocket對(duì)象client負(fù)責(zé)實(shí)際的通信功能,和一個(gè)定時(shí)器keepAliveTimer用于實(shí)現(xiàn)保活定時(shí)功能。
connect方法通過(guò)client對(duì)象來(lái)和接收端建立連接。在建立連接后,connect方法還會(huì)激活?;疃〞r(shí)器keepAliveTimer,保活定時(shí)器會(huì)定時(shí)調(diào)用sendKeepAlive方法發(fā)送?;顖?bào)文。disConnect方法則通過(guò)client對(duì)象實(shí)現(xiàn)斷開(kāi)連接功能,同時(shí)關(guān)閉保活定時(shí)器。
sendFile方法調(diào)用了sendName、sendData和sendHash方法來(lái)發(fā)送文件。sendFile方法在開(kāi)始執(zhí)行時(shí)會(huì)關(guān)閉?;疃〞r(shí)器,在方法執(zhí)行完畢后會(huì)打開(kāi)保活定時(shí)器。從而避免在發(fā)送文件時(shí)插入?;顖?bào)文。
sendName、sendData和sendHash方法分別用于發(fā)送文件名稱、文件內(nèi)容和文件hash字符串,它們都是通過(guò)client對(duì)象來(lái)實(shí)現(xiàn)具體的報(bào)文發(fā)送功能。
每發(fā)送一幀報(bào)文,發(fā)送器都會(huì)調(diào)用waitAnswer方法來(lái)等待接收端的確認(rèn)。waitAnswer方法通過(guò)client對(duì)象來(lái)接收確認(rèn)報(bào)文。如接收確認(rèn)報(bào)文超時(shí)或確認(rèn)報(bào)文為ERR(0x00),waitAnswer方法就調(diào)用disconnect方法關(guān)閉連接,并發(fā)出信號(hào)通知調(diào)用者文件傳輸失敗。
3.2 接收端實(shí)現(xiàn)
接收軟件的接收器負(fù)責(zé)具體的文件接收,它實(shí)現(xiàn)了FTPAFID協(xié)議的接收端部分。接收器結(jié)構(gòu)如圖7所示。
接收器內(nèi)部的QTcpServer對(duì)象listener負(fù)責(zé)監(jiān)聽(tīng)端口,QTcpSocket對(duì)象worker負(fù)責(zé)具體的通信。
open方法負(fù)責(zé)初始化listener,并調(diào)用listener監(jiān)聽(tīng)端口。在接受連接請(qǐng)求后,將產(chǎn)生套接字對(duì)象賦值給worker,最后調(diào)用run方法處理通信工作。close方法用于停止監(jiān)聽(tīng)端口,關(guān)閉listener。
run方法內(nèi)部循環(huán)調(diào)用worker對(duì)象來(lái)接收?qǐng)?bào)文。收到報(bào)文后,run方法會(huì)用doProcess來(lái)處理報(bào)文。stop方法則用于停止run的循環(huán)邏輯,并關(guān)閉worker。
doProcess是一個(gè)函數(shù)指針。接收器利用doProcess在內(nèi)部維持一個(gè)狀態(tài)機(jī),用以判定什么時(shí)候該接收哪一種報(bào)文。它初始指向doPackage。doPackage根據(jù)報(bào)文的操作碼區(qū)分調(diào)用doKeepAlive或doName。
doKeepAlive方法通過(guò)worker對(duì)象向發(fā)送端返回一個(gè)OK報(bào)文。
doName方法先通過(guò)worker對(duì)象返回一個(gè)OK報(bào)文,然后按照接收到的文件名創(chuàng)建文件對(duì)象file,最后將doProcess指向doData來(lái)處理文件數(shù)據(jù)報(bào)文。
doData方法使用file保存接收到的內(nèi)容;在處理文件內(nèi)容報(bào)文時(shí)doData會(huì)判斷是否到達(dá)文件末尾,如果未到達(dá),doProcess繼續(xù)指向doData方法,否則doProcess會(huì)指向doHash方法來(lái)處理文件hash字符串報(bào)文。
doHash方法在接收完文件hash字符串后,會(huì)將doProcess重置為指向doProcess方法,從而完成一個(gè)狀態(tài)循環(huán)。
4 結(jié)束語(yǔ)
本文設(shè)計(jì)的跨正向隔離裝置傳輸文件的通信協(xié)議,完全能夠滿足電力系統(tǒng)中跨區(qū)傳輸文件的需求,彌補(bǔ)了信息跨區(qū)傳輸?shù)牟槐銌?wèn)題。文中介紹了協(xié)議的報(bào)文格式、工作機(jī)制和狀態(tài)遷移過(guò)程。該協(xié)議設(shè)計(jì)簡(jiǎn)單、易于實(shí)現(xiàn),便于擴(kuò)展,具有一定的通用性。本文給出了基于C++語(yǔ)言/Qt框架的實(shí)現(xiàn)作為參考,不過(guò)采用其他語(yǔ)言或框架也很容易實(shí)現(xiàn)該協(xié)議。協(xié)議的實(shí)現(xiàn)可以采用多種方式,協(xié)議的設(shè)計(jì)也可以根據(jù)具體的實(shí)際需要來(lái)擴(kuò)展。
參考文獻(xiàn):
[1]王子,徐澄宇.正向隔離裝置在電力信息外網(wǎng)中的應(yīng)用[J].電腦開(kāi)發(fā)與應(yīng)用,2010,23(8):59-61.
[2]南瑞集團(tuán)公司信息通信技術(shù)分公司.SysKeeper-2000網(wǎng)絡(luò)安全隔離設(shè)備(正向單比特版)用戶手冊(cè)[Z].2010.endprint