王璇 王亮 楊玻 中國(guó)航空工業(yè)集團(tuán)公司西安航空計(jì)算技術(shù)研究所
隨著網(wǎng)絡(luò)通信在航空領(lǐng)域使用日趨廣泛,我們對(duì)于高可靠的網(wǎng)絡(luò)通信要求也是越來(lái)越高。因此操作系統(tǒng)中網(wǎng)絡(luò)的支持程度就顯得尤為重要。在現(xiàn)行眾多的操作系統(tǒng)中,Linux支持多用戶、多進(jìn)程、多線程,實(shí)時(shí)性好,功能強(qiáng)大且穩(wěn)定。在通信和網(wǎng)絡(luò)功能方面,Linux優(yōu)于其它操作系統(tǒng)。其它操作系統(tǒng)不包含如此緊密的內(nèi)核結(jié)合在一起的聯(lián)接網(wǎng)絡(luò)的能力,也沒(méi)有內(nèi)置這些聯(lián)網(wǎng)特性的靈活性。而Linux為用戶提供了完善的、強(qiáng)大的網(wǎng)絡(luò)功能。
Socket作為UNIX的進(jìn)程通信機(jī)制,通常也稱作“套接字”,用于描述IP地址和端口號(hào),是一個(gè)通信鏈的句柄,可以用來(lái)實(shí)現(xiàn)不同虛擬機(jī)或不同計(jì)算機(jī)之間的通信。套接字通過(guò)調(diào)用系統(tǒng)提供的庫(kù)函數(shù)實(shí)現(xiàn)數(shù)據(jù)傳輸,不需要過(guò)多了解底層的細(xì)節(jié),從而完成設(shè)備和網(wǎng)絡(luò)之間的通信。
Socket編程過(guò)程分為服務(wù)器端和客戶端編程,通信過(guò)程如圖1所示。
圖1 服務(wù)器端和客戶端Socket通信過(guò)程
Linux環(huán)境下的Socket編程是通過(guò)套接字的相關(guān)接口來(lái)實(shí)現(xiàn)的,應(yīng)用程序可以通過(guò)Socket接口來(lái)收發(fā)數(shù)據(jù)。通信過(guò)程如下:
首先創(chuàng)建套接字socket(),然后服務(wù)器端綁定套接字bind(),即將本地主機(jī)的IP地址、端口號(hào)與創(chuàng)建的套接字相綁定。綁定完成后,服務(wù)器端監(jiān)聽(tīng)listen(),等待客戶端連接??蛻舳税l(fā)送連接請(qǐng)求connect()??蛻舳说恼?qǐng)求會(huì)觸發(fā)服務(wù)器端和客戶端底層的三次握手,服務(wù)器端接受連接accept()。成功建立連接后,雙方就可以進(jìn)行數(shù)據(jù)收發(fā)了。一般使用send()發(fā)送數(shù)據(jù),使用recv()來(lái)接收數(shù)據(jù)。以上,Socket就連接了客戶端和服務(wù)器端的應(yīng)用程序。在雙方不需要通信時(shí),可以使用close()關(guān)閉連接。
上面介紹了Socket的網(wǎng)絡(luò)通信原理,現(xiàn)在我們就可以對(duì)數(shù)據(jù)傳輸軟件進(jìn)行設(shè)計(jì)了。這是一個(gè)運(yùn)行在Linux操作系統(tǒng)上基于Socket的客戶端程序,我們主要從軟件概述、Linux定時(shí)器使用、連接保持模塊、數(shù)據(jù)發(fā)送模塊和數(shù)據(jù)接收模塊等5個(gè)方面進(jìn)行闡述。
本軟件運(yùn)行在一個(gè)裝有Ubuntu Linux操作系統(tǒng)的航空設(shè)備上。該設(shè)備通過(guò)網(wǎng)線與數(shù)據(jù)庫(kù)服務(wù)器相連接,并將設(shè)備和服務(wù)器的IP地址設(shè)置在同一網(wǎng)段中。在客戶端與服務(wù)器端建立連接后,客戶端主動(dòng)向服務(wù)器端請(qǐng)求上層應(yīng)用軟件所需要的數(shù)據(jù),服務(wù)器端接收到指令后找到相應(yīng)數(shù)據(jù)返回給客戶端,供上層應(yīng)用使用。由于上層應(yīng)用隨時(shí)可能下發(fā)數(shù)據(jù)傳輸請(qǐng)求,故客戶端應(yīng)周期性判斷與服務(wù)器端的連接狀態(tài),保證在上層應(yīng)用下發(fā)命令時(shí)客戶端和服務(wù)器端是通信正常的。
Linux系統(tǒng)提供了毫秒級(jí)定時(shí)器itimerval,它是一個(gè)有兩個(gè)成員變量it_value和it_interval的結(jié)構(gòu)體。it_value指定時(shí)器安裝后首次啟動(dòng)的初始值,it_interval指定時(shí)器重啟動(dòng)的間隔值。本軟件將它們都設(shè)置為1秒,即定時(shí)器啟動(dòng)后將會(huì)以1秒為間隔周期觸發(fā)。接著使用setitimer()函數(shù)使方才設(shè)置的定時(shí)器生效,并使用signal()將中斷處理函數(shù)掛接入該定時(shí)器。這樣,系統(tǒng)每秒就能運(yùn)行一次中斷處理函數(shù),它包含連接保持模塊、數(shù)據(jù)發(fā)送模塊和數(shù)據(jù)接收模塊。
客戶端在Socket初始化完成后,會(huì)周期調(diào)用connect()與服務(wù)器端嘗試建立連接,如果建立連接成功,則會(huì)給服務(wù)器端發(fā)送連接保持命令字,如果在超時(shí)時(shí)間內(nèi)服務(wù)器返回了相應(yīng)命令字,說(shuō)明連接保持。這時(shí),上層應(yīng)用就可以下發(fā)傳輸數(shù)據(jù)的命令了;如果連續(xù)三個(gè)周期服務(wù)器沒(méi)有在超時(shí)時(shí)間內(nèi)回應(yīng)命令字,則判定服務(wù)器下線,斷開(kāi)并關(guān)閉其連接。下個(gè)周期繼續(xù)調(diào)用connect()嘗試與其建立連接。
在連接保持的狀態(tài)下,當(dāng)上層應(yīng)用下發(fā)數(shù)據(jù)傳輸命令,客戶端就可以使用send()函數(shù)來(lái)發(fā)送數(shù)據(jù)了。如果出現(xiàn)了小于發(fā)送長(zhǎng)度的情況,就代表著數(shù)據(jù)有部分沒(méi)有發(fā)送完成,只是發(fā)送了一部分,這時(shí)就需要再次發(fā)送來(lái)完成數(shù)據(jù)發(fā)送。
當(dāng)服務(wù)器端接收到客戶端所請(qǐng)求的數(shù)據(jù)時(shí),服務(wù)器端就會(huì)回復(fù)數(shù)據(jù),即客戶端使用recv()接收數(shù)據(jù)。由于服務(wù)器端不一定會(huì)立即回復(fù)數(shù)據(jù),所以要設(shè)置超時(shí)時(shí)間。在超時(shí)時(shí)間內(nèi),客戶端接收到了足夠數(shù)量的數(shù)據(jù),并進(jìn)行累加和校驗(yàn),校驗(yàn)成功,那么傳遞給上層應(yīng)用;校驗(yàn)失敗,則通知服務(wù)器端重傳。如果服務(wù)器端回復(fù)超時(shí),則也需要服務(wù)器端重傳。
程序采用C語(yǔ)言編寫(xiě),編譯Linux客戶端時(shí)需要執(zhí)行如下編譯命令:gcc -o client client.c,然后運(yùn)行此執(zhí)行文件,命令如下:
在Linux系統(tǒng)下執(zhí)行完上述命令后,設(shè)備就和數(shù)據(jù)庫(kù)服務(wù)器建立連接了。設(shè)備先向服務(wù)器發(fā)送請(qǐng)求數(shù)據(jù)命令,再接收服務(wù)器發(fā)來(lái)的數(shù)據(jù),是典型的“主從模式”一發(fā)一收。
Linux網(wǎng)絡(luò)具有較高的安全性,可以進(jìn)行網(wǎng)絡(luò)資源的共享,完成網(wǎng)絡(luò)通信。它還包含著很多網(wǎng)絡(luò)協(xié)議,擁有開(kāi)放的源代碼,我們可以利用Linux網(wǎng)絡(luò)進(jìn)行基于Socket的網(wǎng)絡(luò)通信技術(shù)的開(kāi)發(fā)。Socket作為其中的接口起著舉足輕重的作用,連接起了網(wǎng)絡(luò)設(shè)備和應(yīng)用程序與下層協(xié)定,從而完成設(shè)備和網(wǎng)絡(luò)之間的網(wǎng)路通信。