引言
控制網(wǎng)絡(luò)一般指以控制“事物對象”為特征的計算機(jī)網(wǎng)絡(luò)系統(tǒng),,簡稱Infranet(infrastructure network),,它處在企業(yè)網(wǎng)(Intranet)的底層,構(gòu)成了整個企業(yè)網(wǎng)的基礎(chǔ),。近些年來,,在控制網(wǎng)絡(luò)中采用了現(xiàn)場總線(Field Bus)和工業(yè)以太網(wǎng)(Ethernet)兩種技術(shù)。出現(xiàn)這種情況主要有兩個原因:第一,目前存在多種現(xiàn)場總線標(biāo)準(zhǔn),,不同的標(biāo)準(zhǔn)采用完全不同的通信協(xié)議,,也就是說現(xiàn)場總線的開放性不夠;第二,,以太網(wǎng)雖然能夠解決開放性的問題,,并具備成本低廉、技術(shù)成熟等優(yōu)點(diǎn),,但由于以太網(wǎng)最初是被設(shè)計用于以資源共享為目的的計算機(jī)局域網(wǎng),,因此在實(shí)時性和可靠性上暫時還不能完全滿足工業(yè)控制的要求。事實(shí)上,,目前一個較大規(guī)模的控制網(wǎng)絡(luò)往往綜合采用了這兩種技術(shù),。在現(xiàn)場層,由于強(qiáng)調(diào)實(shí)時性,、可靠性和安全性,常采用現(xiàn)場總線技術(shù),;在監(jiān)控管理層,,考慮到采用不同標(biāo)準(zhǔn)的控制網(wǎng)段之間的集成以及與高層企業(yè)信息網(wǎng)絡(luò)的集成,一般采用以太網(wǎng)技術(shù)?,F(xiàn)場層的現(xiàn)場總線控制系統(tǒng)FCS(Field Control System)或其它設(shè)備級輕質(zhì)網(wǎng)絡(luò)通過網(wǎng)關(guān)或嵌入式HTTP服務(wù)器與高層以太網(wǎng)相連,。這樣,不僅采用不同協(xié)議的控制網(wǎng)段能夠?qū)崿F(xiàn)互聯(lián),,而且各個控制網(wǎng)段能方便地與高層企業(yè)信息網(wǎng)互通,,從而最終實(shí)現(xiàn)企業(yè)網(wǎng)的管控一體化和對現(xiàn)場設(shè)備的Internet遠(yuǎn)程監(jiān)控。通過以上分析可以看出,,控制網(wǎng)絡(luò)中的網(wǎng)關(guān)或嵌入式HTTP服務(wù)器起著連接現(xiàn)場層和監(jiān)迭管理層的作用,,因此它是整個控制網(wǎng)絡(luò)的關(guān)鍵設(shè)備。
網(wǎng)關(guān)或嵌入式HTTP服務(wù)器與傳統(tǒng)的嵌入式系統(tǒng)相比,,有一些不同的特性,。傳統(tǒng)的嵌入式系統(tǒng)是面向應(yīng)用、有一些不同的特性,。傳統(tǒng)的嵌入式系統(tǒng)是面向應(yīng)用,、面向產(chǎn)品的,強(qiáng)調(diào)成本和高效設(shè)計系統(tǒng),,因此本質(zhì)上不具備通用性和可移植性,。網(wǎng)關(guān)或嵌入式HTTP服務(wù)器由于處在現(xiàn)場層和監(jiān)控管理層的中間,因此它與具體應(yīng)用和產(chǎn)品是一種弱耦合的關(guān)系,。同時,,技術(shù)發(fā)展的趨勢是:硬件成本越來越低,功能越來越強(qiáng),,越來越多的芯片和板卡具備“平臺”的特點(diǎn),,適用于多種應(yīng)用場合,。嵌入式實(shí)時操作系統(tǒng)(Embedded Real Time Operationg System)的發(fā)展更是為嵌入式軟件提供了一個通用的軟件平臺。綜上所述,,在網(wǎng)關(guān)或嵌入式HTTP服務(wù)器設(shè)計中,,考慮通過選用適合的硬件和嵌入式實(shí)時操作系統(tǒng),使整個系統(tǒng)具備相當(dāng)?shù)耐ㄓ眯院涂梢浦残?。對于連接不同的設(shè)備級輕質(zhì)網(wǎng)絡(luò)或不同的應(yīng)用,,只需要通過更換硬件模塊和對代碼作最小的修改即可實(shí)現(xiàn)。
1 基于Linux的嵌入式HTTP服務(wù)器的結(jié)構(gòu)
為了實(shí)現(xiàn)設(shè)計目標(biāo),,嵌入式HTTP服務(wù)器一般應(yīng)采用功能較強(qiáng)的能用PC,、工業(yè)PC、或高檔MPU作為硬件平臺,,嵌入式實(shí)時操作系統(tǒng)作為軟件平臺進(jìn)行平發(fā),。硬件平臺應(yīng)具備以太網(wǎng)口和一個或多個通信模塊,比如RS232,、RS485,、CAN通信卡等。嵌入式實(shí)時操作系統(tǒng)實(shí)現(xiàn)了TCP/IP等網(wǎng)絡(luò)協(xié)議,,并提供實(shí)時任務(wù),、進(jìn)程管理、內(nèi)存管理,、文件系統(tǒng),、API等功能。
Linux操作系統(tǒng)是一種多進(jìn)程,,多用戶的通用操作,。由于它具備免費(fèi)、源碼公開,、內(nèi)核可裁減,、支持多線程、網(wǎng)絡(luò)功能強(qiáng)大,、設(shè)計精巧,、性能穩(wěn)定的特點(diǎn),因此近年它也被廣泛用到嵌入式系統(tǒng)的設(shè)計中,。一個應(yīng)用于嵌入式系統(tǒng)的Linux經(jīng)過裁減和重新編譯后只包括進(jìn)程管理,、內(nèi)存管理、文件系統(tǒng),、若干個驅(qū)動程序和實(shí)用的函數(shù)等,。
下面以本人參與的轉(zhuǎn)子秤控制系統(tǒng)為例來說明一個基于Linux的嵌入式HTTP服務(wù)器的結(jié)構(gòu)。轉(zhuǎn)子秤是水泥工業(yè)中的關(guān)鍵計量喂料設(shè)備,一條大型的生產(chǎn)線需要許多臺轉(zhuǎn)子秤,,對轉(zhuǎn)子秤的控制涉及到重量,、轉(zhuǎn)速、溫度,、一氧化碳含量等若干個參量,。由于現(xiàn)場環(huán)境的高噪聲、高粉塵,、高電磁干擾,,無法在現(xiàn)場配備鍵盤、顯示器,、觸摸屏等人機(jī)交互設(shè)備,,無法在現(xiàn)場實(shí)現(xiàn)對設(shè)備的監(jiān)控和維護(hù)。同時,,一條生產(chǎn)線有多臺轉(zhuǎn)子秤,,為每臺轉(zhuǎn)子秤配備人機(jī)交互設(shè)備也是不經(jīng)濟(jì)的。為此,,考慮為整個系統(tǒng)設(shè)計一個嵌入式HTTP服務(wù)器,,各轉(zhuǎn)子秤控制器與嵌入式HTTP服務(wù)器用CAN總線相連。通過嵌入式HTTP服務(wù)器實(shí)現(xiàn)對整個系統(tǒng)的在線監(jiān)控和遠(yuǎn)程監(jiān)控,。在嵌入式HTTP服務(wù)器的設(shè)計中,,選用研祥公司PC104總線的486X嵌入式CPU卡作為硬件平臺,,該板卡是具有128MB的在板ROM,、CF卡接口和以太網(wǎng)接口等。選擇該板卡的原因是PC104總線的功能擴(kuò)展模塊非常豐富,,通過選擇不同的模塊很容易就支持多種總線,。軟件平臺方面,選用Linux2.0內(nèi)核并對它作適當(dāng)裁減,。整個嵌入式HTTP服務(wù)器的結(jié)構(gòu)簡圖如圖1所示,。
2 基于Linux的嵌入式HTTP服務(wù)器的設(shè)計
工控領(lǐng)域的嵌入式HTTP服務(wù)器應(yīng)該具備如下基本功能。
①實(shí)時數(shù)據(jù)發(fā)布,。實(shí)時數(shù)據(jù)主要包括系統(tǒng)運(yùn)行過程中設(shè)備的各種狀態(tài)信息,。嵌入式HTTP服務(wù)器將實(shí)時數(shù)據(jù)以網(wǎng)頁形式發(fā)布到Internet上,且動態(tài)實(shí)時刷新,??蛻艨梢酝ㄟ^瀏覽器訪問這些實(shí)時信息。
②參數(shù)設(shè)置,。參數(shù)包括運(yùn)行參數(shù)和設(shè)備狀態(tài)參數(shù),,如各種初始值、常數(shù)等。嵌入式HTTP服務(wù)器接收到客戶提交的參數(shù)設(shè)備請求后,,執(zhí)行參數(shù)寫入操作,。
③遠(yuǎn)程實(shí)時控制。遠(yuǎn)程實(shí)時控制允許遠(yuǎn)程用戶在線地控制系統(tǒng)中的相應(yīng)執(zhí)行機(jī)構(gòu),,比如電機(jī),、電磁閥等。嵌入式HTTP服務(wù)器接收到遠(yuǎn)方客戶提交的控制操作請求后,,將下發(fā)控制命令驅(qū)動監(jiān)控系統(tǒng)中相應(yīng)的執(zhí)行機(jī)構(gòu),。
④訪問級別設(shè)置和權(quán)限認(rèn)證。只有權(quán)限不低于要求訪問級別的客戶,,經(jīng)嵌入式HTTP服務(wù)器認(rèn)證后,,方可進(jìn)行其權(quán)限范圍內(nèi)的監(jiān)控操作。
3 主要實(shí)現(xiàn)技術(shù)
3.1 超文本傳輸協(xié)議
HTTP協(xié)議是一個面向事務(wù),、無狀態(tài)的應(yīng)用層協(xié)議,。在傳輸層,HTTP協(xié)議使用請求(request)/響應(yīng)(response)模型,。一次簡單的HTTP事務(wù)包括以下過程,。首先,客戶(瀏覽器)發(fā)起和建立一條到服務(wù)器的TCP連接,。然后,,客戶發(fā)送一個HTTP請求到服務(wù)器,請求包含方法,、URI,、協(xié)議版本和一個類MIME報文。服務(wù)器解析HTTP請求后,,給出相應(yīng)的HTTP響應(yīng),,響應(yīng)包括協(xié)議版本、狀態(tài)碼,、解釋狀態(tài)碼的簡短短語和一個類MIME報文,。最后,釋放TCP連接,。Linux操作系統(tǒng)為用戶提供了稱為BSD Socket的網(wǎng)絡(luò)編程接口,。利用其中的TCP套接口函數(shù),可以非常方便地實(shí)現(xiàn)HTTP協(xié)議,。
HTTP1.0為每一次HTTP請求/響應(yīng)建立一條新的TCP連接,,由于建立一條TCP連接要經(jīng)歷3次握手,因此效率不高,。HTTP1.1提出了可持續(xù)性連接的概念,。HTTP1.1只建立一次TCP連接,,而重復(fù)地使用它傳送一條素的請求/響應(yīng)消息,減少了額外開銷,。在嵌入式HTTP服務(wù)器中,,一般使用HTTP1.1協(xié)議。HTTP1.1協(xié)議的細(xì)節(jié)請參考RFC2616,。
3.2 通用網(wǎng)關(guān)接口CGI
參數(shù)設(shè)置和遠(yuǎn)程控制功能都是通過CGI(通用網(wǎng)關(guān)接口)程序和表單實(shí)現(xiàn)的,。CGI使用HTML表單向Web服務(wù)器發(fā)送信息?;菊Z法如下:
<FORM METHOD=get/post ACTION=URL></FORM>
其中,,METHOD屬性指定將數(shù)據(jù)傳送到Web服務(wù)器的方法。輸入方法有兩種:GET和POST,。ACTION屬性定義要對表單數(shù)據(jù)進(jìn)行處理的CGI腳本的URL,。
CGI的工作流程是首先由瀏覽器將用戶輸入的數(shù)據(jù)傳遞給Web服務(wù)器,Web服務(wù)器根據(jù)接收到的數(shù)據(jù)設(shè)置環(huán)境變量并啟動CGI腳本,,CGI腳本從環(huán)境變量中讀取所需要的數(shù)據(jù)并進(jìn)行相應(yīng)處理,,最后使用STDOUT輸出HTML形式的結(jié)果文件,經(jīng)Web服務(wù)器送回瀏覽器,,最終顯示給用戶,。傳統(tǒng)的CGI程序與服務(wù)器代碼分開,是一個符號CGI標(biāo)準(zhǔn)的可執(zhí)行文件,,并儲存在CF卡等存儲設(shè)備上,,一般用腳本語言編寫??紤]到嵌入式HTTP服務(wù)器要求速度快,,功能和代碼都盡可能精簡的特點(diǎn),可以把原先由可執(zhí)行文件完成的功能用C函數(shù)實(shí)現(xiàn),,放在服務(wù)器代碼內(nèi)部,,并直接從HTTP請求報文接收數(shù)據(jù),。與傳統(tǒng)CGI程序相比,,這種方法具備如下特點(diǎn):
*不需要標(biāo)準(zhǔn)輸入,CGI函數(shù)可以直接獲取到瀏覽器送來的信息,;
*不需要標(biāo)準(zhǔn)輸出,,CGI函數(shù)可以直接將數(shù)據(jù)送回給瀏覽器;
*不需要環(huán)境變量,,CGI和Web服務(wù)器在同一程序中實(shí)現(xiàn),,不需要環(huán)境變量來交換信息。
3.3 自定義標(biāo)記
要在網(wǎng)頁中顯示工控系統(tǒng)中大量的實(shí)時數(shù)據(jù),,常規(guī)方法是將HTML代碼直接集成到程序代碼中,,或者反之將C程序代碼集成到HTML標(biāo)記語言中,。這兩種方法均要求開發(fā)人員對HTML標(biāo)記語言的語法細(xì)節(jié)非常熟悉。網(wǎng)頁或程序結(jié)構(gòu)的單方面調(diào)整都將導(dǎo)致整個系統(tǒng)全盤修改,,系統(tǒng)不具備靈活性與可擴(kuò)展性,。HTML的精髓在于該語言的“標(biāo)記”性,各種不同標(biāo)記的具體含義是由服務(wù)器和瀏覽器進(jìn)行解析,。因此,,當(dāng)現(xiàn)有標(biāo)記不能滿足新的應(yīng)用需求時,可以自行定義新的標(biāo)記,,只需服務(wù)器將自定義標(biāo)記解析為標(biāo)準(zhǔn)標(biāo)記,,然后傳送給瀏覽器即可。在本項目中,,主要的實(shí)時數(shù)據(jù)轉(zhuǎn)速,、重量、一氧化碳含量等狀態(tài)信息,,可以定義相應(yīng)的標(biāo)記,。服務(wù)器中解析相應(yīng)標(biāo)記的函數(shù)同樣用C語言來實(shí)現(xiàn)。運(yùn)行時,,當(dāng)客戶端發(fā)出查看某實(shí)時網(wǎng)頁的請求后,,嵌入式HTTP服務(wù)器將相應(yīng)的網(wǎng)頁文件從電子盤加載到內(nèi)存進(jìn)行逐項解析。當(dāng)辨識出自定義標(biāo)記后,,就調(diào)用相應(yīng)的函數(shù),。該函數(shù)返回該標(biāo)記對應(yīng)的當(dāng)前值,并置換HTML文件流中的自定義標(biāo)記,。最后,,嵌入式HTTP服務(wù)器將解析結(jié)果發(fā)送給客戶端。實(shí)時網(wǎng)頁的設(shè)計與相應(yīng)的HTTP服務(wù)器處理程序得以分離,,處于一種弱耦合關(guān)聯(lián)狀態(tài),。這樣,網(wǎng)頁界面的調(diào)整不會影響HTTP服務(wù)器的程序設(shè)計,,HTTP服務(wù)器程序的修改也與網(wǎng)頁界面設(shè)計無關(guān),,整個嵌入式HTTP服務(wù)器具備靈活性和可擴(kuò)展性。
3.4 多線程
最初的進(jìn)程定義包含程序,、資源及其執(zhí)行三部分,,其中程序通常指代碼,資源通常包括 內(nèi)存資源,、I/O資源,、信號處理等,而程序的執(zhí)行指執(zhí)行上下文,,這一部分后來發(fā)展為線程,。在線程的概念出現(xiàn)以前,,為了減小進(jìn)程切換的開銷,操作系統(tǒng)設(shè)計者逐漸修改正進(jìn)程的概念,,允許將進(jìn)程所占有的資源從其主體剝離出來,,允許某些進(jìn)程共離享一部分資源,例如文件,、信號,、數(shù)據(jù)內(nèi)存、甚至代碼,,這就是輕質(zhì)進(jìn)程的概念,。Linux內(nèi)核的2.0.x版本就已經(jīng)實(shí)現(xiàn)了輕質(zhì)進(jìn)程。應(yīng)用程序可以通過一個統(tǒng)一的clone()系統(tǒng)調(diào)用接口,,用不同的參數(shù)指定創(chuàng)建輕質(zhì)進(jìn)程還是普通進(jìn)程,。在內(nèi)核中,clone()調(diào)用經(jīng)過參數(shù)傳遞和解釋后會調(diào)用do_fork(),,這個核內(nèi)函數(shù)同時也是fork,、vfork()系統(tǒng)調(diào)用的最終實(shí)現(xiàn)。在do_fork()中,,不同的flone_flags將導(dǎo)致不同的行為,。在LinuxThreads中,使用(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND)參數(shù)調(diào)用clone()創(chuàng)建“線程”,,表示共享內(nèi)存,、共享文件系統(tǒng)、共享文件描述符表,,以及共享信號處理方式,。Linux操作系統(tǒng)下,已經(jīng)實(shí)現(xiàn)基于輕質(zhì)進(jìn)程的符號POSIX1003.C標(biāo)準(zhǔn)的線程庫LinuxThreads,。
在傳統(tǒng)的Unix服務(wù)器程序設(shè)計中,,為了使服務(wù)器具備并發(fā)處理連接的能力,通常采用父進(jìn)程處理連接,,并調(diào)用fork()創(chuàng)建子進(jìn)程來處理用戶請求的方法,。這種方法的缺點(diǎn)是進(jìn)程創(chuàng)建慢,耗費(fèi)資源,,進(jìn)程切換開銷大,,進(jìn)程之間通信比較困難等,,不適用對資源,、速度有要求的嵌入式系統(tǒng)。因此,,在嵌入式HTTP服務(wù)器的開發(fā)中使用線程的方法,。利用LinuxThreads提供的pthread_create()等函數(shù)派生出線程,,也即輕質(zhì)進(jìn)程來處理多個HTTP請求。
4 工作流程和代碼設(shè)計
4.1工作流程
嵌入式HTTP服務(wù)器程序開始運(yùn)行時,,主進(jìn)程首先創(chuàng)建一個接口,,并和主機(jī)地址綁定到一起,隨后置為被動監(jiān)聽狀態(tài),,等待客戶端連接請求的到來,。分別用函數(shù)socket()創(chuàng)建一個接口,bind()綁定地址,,listen()監(jiān)聽,,accept()接收來完成。當(dāng)建立一個TCP連接后,,函數(shù)accept()返回一個新的套接口描述符,,主進(jìn)程就創(chuàng)建一個新的子線程(輕質(zhì)進(jìn)程)處理這個新的連接。
子線程用于處理每具體的HTTP請求,。子線程首先解析用戶的HTTP請求,。當(dāng)用戶請求一個網(wǎng)頁時,子線程查找文件系統(tǒng),。如果該網(wǎng)頁文件存在,,且通過權(quán)限認(rèn)證,就把它從CF卡讀入內(nèi)存并掃描,,發(fā)現(xiàn)有自定義標(biāo)記則調(diào)用相應(yīng)函數(shù)進(jìn)行處理,,最后把結(jié)果返回給瀏覽器;否則給一個簡單的出錯消息,。當(dāng)用戶是上傳數(shù)據(jù)時,,子線程調(diào)用相應(yīng)函數(shù)讀取數(shù)據(jù)進(jìn)行處理,并返回處理結(jié)果給瀏覽器,。
4.2 代碼設(shè)計
在嵌入式HTTP服務(wù)器的代碼設(shè)計中,,考慮到代碼的移植性和擴(kuò)展性,利用C語言實(shí)現(xiàn)了面向?qū)ο箫L(fēng)格的代碼結(jié)構(gòu),。代碼主要由兩上數(shù)據(jù)結(jié)構(gòu)request_inf和response_inf以及其上一組操作函數(shù)組成,。
結(jié)構(gòu)request_inf和response_inf分別用來保存HTTP請求報文和響應(yīng)報文的所有信息。在結(jié)構(gòu)定義時,,應(yīng)根據(jù)具體應(yīng)用特點(diǎn)設(shè)計結(jié)構(gòu)包含的成分,。
嵌入式HTTP服務(wù)器的函數(shù)包括通用函數(shù)、CGI函數(shù)和自定義標(biāo)記處理函數(shù)等,,其中通用函數(shù)是一些與HTTP1.1協(xié)議有關(guān)的函數(shù),。
(1)通用函數(shù)
*void prase_request_line(char *,struct *request_inf)
該函數(shù)用來解析HTTP請求報文的請求行(Request_Line),并把相應(yīng)信息存放在結(jié)構(gòu)request_inf中,。其中,,對請求行中URI部分的解析包括兩種情況,。如果用戶請求一個網(wǎng)頁,則獲取文件路徑,、文件類型,;如果用戶要求上傳數(shù)據(jù),則把數(shù)據(jù)放在一個字符數(shù)組中,。然后將文件路徑和類型,,或者指向該數(shù)組的指針、方法,、版本號信息都放入結(jié)構(gòu)request_inf中,。
*void prease_general_header(char*,struct*request_inf)
該函數(shù)用來解析HTTP請求報文的調(diào)用首部(General_Header)。之所以把此函數(shù)與函數(shù)prase_request_line()分開,,是考慮到程序的修植性和擴(kuò)展性,。請求行和通用首部是請求報文中的不同部分,不不同的場合下,,要求解析的信息可能存在差導(dǎo)師,。同時,這樣也能使程序結(jié)構(gòu)更清楚,。比如,,本項目要從通用首部解析字段Keep_Alive。該字段指明一個最長的時間或最大請求數(shù)目,,在此范圍內(nèi)可以保持TCP連接不被釋放(即前文提到的HTTP1.1的持續(xù)連接特性,,persistent connection)。
*void prase_request_header(char*,struct*request_inf)
void prase_entity_header(char*,struct*request_inf)
HTTP請求報文的請求頭部用來說明瀏覽器的一些信息,,實(shí)體頭部則用來說明請求報文中可能存在的實(shí)體主體信息,。本項目實(shí)際上并不需要使用這兩個函數(shù)來獲取相關(guān)信息,但考慮到程序的擴(kuò)展性和移植性,,此處仍然把它列出來,,它們是兩個空函數(shù)。
*send_status_line(int fd,struct *response_inf)
此函數(shù)用來產(chǎn)生一個HTTP響應(yīng)報文的狀態(tài)行(Status_line),。狀態(tài)行包括三部分內(nèi)容,,即HTTP版本、狀態(tài)碼以及解釋狀態(tài)碼的簡單短語,。這些信息預(yù)先放在結(jié)構(gòu)response_inf中,。
*send_general_header(int fd,struct*response_inf)
send_response_header(int fd,struct*response_inf)
send_entity_header(int fd,struct*response_inf)
這三個函數(shù)分別用來產(chǎn)生HTTP響應(yīng)報文的通用首部、響應(yīng)首部(Response_header)和實(shí)體首部,。嵌入式HTTP服務(wù)器是一個瘦服務(wù)器,,功能非常簡單。因此HTTP響應(yīng)報文的通用首部、響應(yīng)首部和實(shí)體首部中的可選字段許多是不需要的,,還有許多是固定不變的,,例如Last_modified和Content_type字段,。Last_modified字段指出資源上次被修改的時間并由接收方解釋,。如果接收方已有此資源的拷貝,但此拷貝比Last-Modified域所指定的要舊,,那該拷貝就是過期的,。由于網(wǎng)頁文件中含有自定義標(biāo)記,具有實(shí)時性,,所以此字段根本沒有含有Content_type字段指出實(shí)體的媒體類型,,本項目中的嵌入式HTTP服務(wù)器被設(shè)計成只支持HTML類型,因此該字段的內(nèi)容總是Content_type=text/html,。有關(guān)服務(wù)器和資源的所有標(biāo)題域信息都被放入結(jié)構(gòu)response_inf中,。
*send_white_line(int fd)
此函數(shù)用于實(shí)體首部和實(shí)體之間傳送一個空白行。
*void send_entity_body(int fd,char *buff_file)
此函數(shù)用來傳遞實(shí)體主體,,實(shí)體主體實(shí)際上是一個處理后的網(wǎng)頁文件,,它被放在指針buff_file指向的緩沖區(qū)內(nèi)。
*void zero_request_inf(struct*request_inf)
void zero_response_inf(struct*response_inf)
這兩個函數(shù)用于結(jié)構(gòu)request_inf和response_inf清零,。
*void get_file(struct*request_inf,struct * response_inf,char*buff_file,void*,void*)
該函數(shù)用來處理用戶HTTL請求,。首先,函數(shù)會檢查request_inf結(jié)構(gòu),,判斷用戶是請求一個網(wǎng)頁文件還是上傳數(shù)據(jù),。當(dāng)用戶請求網(wǎng)頁文件時,函數(shù)將根據(jù)request_inf結(jié)構(gòu)中的文件路徑信息,,在文件系統(tǒng)錄找此文件,。如果文件不存在或不具備權(quán)限,則函數(shù)將狀態(tài)碼和解釋短語寫入結(jié)構(gòu)response_inf,,然后直接返回,;否則讀取文件并調(diào)用自定義標(biāo)記處理函數(shù),對標(biāo)記進(jìn)行處理,,處理過的網(wǎng)頁文件被放入buff_file指向的緩沖區(qū)內(nèi),,并把狀態(tài)碼、解釋短路和與實(shí)體有關(guān)的一些信息寫入結(jié)構(gòu)response_inf,。當(dāng)用戶上傳數(shù)據(jù)時,,該函數(shù)調(diào)用CGI處理函數(shù)向CAN總線網(wǎng)絡(luò)發(fā)送幀,然后將狀態(tài)碼和解釋短路寫入結(jié)構(gòu)response_inf,。利用狀態(tài)碼和解釋短語只能用“200,OK”或“500,,Internal Server Error”等,簡單反映執(zhí)行情況。用戶要獲取詳細(xì)信息,,可待一段合適的時間后請求網(wǎng)頁文件,。函數(shù)中兩個void指針分別指向自定義標(biāo)記處理函數(shù)和CGI處理函數(shù),或者對應(yīng)的函數(shù)指針數(shù)組,。
(2)自定義標(biāo)記處理函數(shù)和CGI處理函數(shù)
自定義標(biāo)記處理函數(shù)用于對自定義的處理,,每一類自定義標(biāo)記對對應(yīng)一種自定義標(biāo)記處理函數(shù),同一類自定義標(biāo)記的不同數(shù)據(jù)點(diǎn)利用參數(shù)來區(qū)分,,比如轉(zhuǎn)子秤1的重量標(biāo)記可以用weight1來表示,。所有的自定義標(biāo)記處理函數(shù)被放在一起,構(gòu)成一個函數(shù)指針數(shù)組,。自定義標(biāo)記處理函數(shù)向CAN總線網(wǎng)絡(luò)發(fā)送遠(yuǎn)程幀和接收數(shù)據(jù)幀,,獲取相應(yīng)的狀態(tài)信息。CGI總線網(wǎng)絡(luò)發(fā)送遠(yuǎn)程幀和接收數(shù)據(jù)幀,,獲取相應(yīng)的狀態(tài)信息,。CGI處理函數(shù)用變量名來區(qū)分,同一類變量對應(yīng)一種CGI處理函數(shù),。與自定義標(biāo)記處理函數(shù)類似,,所有的CGI處理函數(shù)也被放在一起,構(gòu)成一個函數(shù)指針數(shù)組,。由于自定義標(biāo)記函數(shù)和CGI處理函數(shù)類型眾多,,這里就不列舉了。
結(jié)語
我們設(shè)計的嵌入式HTTP服務(wù)器具備良好的通用性和可移植性,。通過更換或增加PC104通信模塊,,該服務(wù)器能夠支持不同的現(xiàn)場總線,或同時連接幾種不同的設(shè)備級輕質(zhì)網(wǎng)絡(luò),。同時在服務(wù)器代碼設(shè)計中,,用C語言實(shí)現(xiàn)了面向?qū)ο箫L(fēng)格的代碼結(jié)構(gòu)。這樣,,如果要求服務(wù)器端具備更多的特性,,只需要簡單修改結(jié)構(gòu)request_inf、response_inf,、操作函數(shù)和網(wǎng)頁文件即可達(dá)到目的,。這種設(shè)計思路不僅適用于嵌入式HTTP服務(wù)器,隨著硬件技術(shù)尤其是嵌入式操作系統(tǒng)技術(shù)的發(fā)展,,它同樣能夠應(yīng)用到其它嵌入式產(chǎn)品的開發(fā)中,。