




已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第3章 嵌入式遠(yuǎn)程監(jiān)控系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)1.1 課程設(shè)計(jì)目的通過(guò)本課程設(shè)計(jì),要對(duì)嵌入式系統(tǒng)的開(kāi)發(fā)有比較深入的學(xué)習(xí)和分析。通過(guò)對(duì)WEB編程、服務(wù)器的架設(shè)、驅(qū)動(dòng)程序的開(kāi)發(fā)這些步驟的深入研究,掌握構(gòu)建一個(gè)完備的嵌入式系統(tǒng)的開(kāi)發(fā)流程。1.2 課程設(shè)計(jì)要求通過(guò)本課程設(shè)計(jì),熟練前面幾章的內(nèi)容。在此基礎(chǔ)上,編寫(xiě)相關(guān)驅(qū)動(dòng)程序,以及CGI和數(shù)據(jù)處理程序完成基于WEB的嵌入式遠(yuǎn)程控制系統(tǒng)。通過(guò)本章的課程設(shè)計(jì),可以初步了解一個(gè)嵌入式系統(tǒng)的基本構(gòu)建過(guò)程,學(xué)習(xí)如何在ARM系統(tǒng)上搭建嵌入式服務(wù)器,并通過(guò)CGI控制外部設(shè)備的一般方法。1.3 系統(tǒng)簡(jiǎn)介嵌入式WEB 服務(wù)器及遠(yuǎn)程測(cè)控總的思想就是網(wǎng)絡(luò)化儀器。完成的目標(biāo)就是設(shè)計(jì)基于Linux 操作系統(tǒng)的遠(yuǎn)程測(cè)控系統(tǒng),并且討論實(shí)踐中的可行性,我們通過(guò)普通的瀏覽器就可以對(duì)遠(yuǎn)端現(xiàn)場(chǎng)的控制和測(cè)量以及獲取遠(yuǎn)端現(xiàn)場(chǎng)的圖像信息。使用嵌入式WEB 服務(wù)器的好處有這樣幾點(diǎn):(1) 遠(yuǎn)程監(jiān)控終端僅需要安裝瀏覽器即可,無(wú)需開(kāi)發(fā)專(zhuān)門(mén)的應(yīng)用軟件,降低系統(tǒng)成本。(2)瀏覽器所在的監(jiān)控終端平臺(tái)與WEB 所在的服務(wù)器平臺(tái)無(wú)關(guān),監(jiān)控終端可以采用多種操作系統(tǒng),真正實(shí)現(xiàn)了跨平臺(tái)。(3)操作界面簡(jiǎn)單統(tǒng)一,表達(dá)直觀生動(dòng),用戶(hù)無(wú)需經(jīng)過(guò)專(zhuān)門(mén)培訓(xùn)。(4)易于擴(kuò)展新的功能,系統(tǒng)升級(jí)僅需在Web 服務(wù)器一端添加相應(yīng)模塊,與遠(yuǎn)程監(jiān)控終端無(wú)關(guān),降低系統(tǒng)升級(jí)維護(hù)費(fèi)用。系統(tǒng)整體結(jié)構(gòu)如下:圖3.1 系統(tǒng)整體結(jié)構(gòu)遠(yuǎn)程監(jiān)控系統(tǒng)所涉及的知識(shí)點(diǎn)很多,主要包括Linux 操作系統(tǒng),內(nèi)核移植,文件系統(tǒng)的移植,服務(wù)器的移植,CGI 程序的移植,CGI 腳本的編寫(xiě),設(shè)備驅(qū)動(dòng)的調(diào)試和JavaScript 腳本,TCP 服務(wù)器與客戶(hù)端,UDP 服務(wù)器與客戶(hù)端,Java 中的多線程技術(shù),Java 畫(huà)圖板及各種控件的添加。下面提供幾張已經(jīng)做好的測(cè)控服務(wù)器的圖片,先達(dá)到一個(gè)感性的認(rèn)識(shí)。圖3.2 是一個(gè)實(shí)時(shí)視頻及溫度測(cè)量遠(yuǎn)程監(jiān)控系統(tǒng),它將采集到的圖像以及溫度參數(shù)在網(wǎng)頁(yè)中顯示出來(lái)。圖3.2 ARM9 遠(yuǎn)程實(shí)時(shí)視頻及溫度測(cè)量在這一章中我們將學(xué)習(xí)一個(gè)基本的嵌入式遠(yuǎn)程監(jiān)控系統(tǒng)的搭建,由于涉及到的知識(shí)點(diǎn)較多,我們只能把其中最主要的知識(shí)簡(jiǎn)要地描述,更多更詳細(xì)的設(shè)計(jì)可以參考手冊(cè)后面的參考文獻(xiàn)。通過(guò)對(duì)本章的學(xué)習(xí),讀者可以了解架設(shè)一個(gè)嵌入式WEB服務(wù)器的全過(guò)程及其要點(diǎn)。1.4 嵌入式WEB服務(wù)器移植1.4.1 BOA的移植1、下載BOA源碼下載地址: / 或者/。最新發(fā)行版本: 0.94.13 下載 boa-0.94.13.tar.gz,注意:從boa 上下載的是boa-0.94.13.tar.gz,按照一般解壓步驟進(jìn)行解壓:# tar xzf boa-0.94.13.tar.gz 2、生成Makefile文件生成Makefile 文件直接運(yùn)行src/configure 文件。 3、修改Makefile文件修改Makefile 文件修改 CC = gcc 為 CC = arm-linux-gcc 修改 CPP = gcc - E 為 CPP = arm-linux-gcc -E4、編譯# make 生成boa 文件 # arm-linux-strip boa 去掉文本信息,使boa 變小# make 生成boa 文件 # arm-linux-strip boa 去掉文本信息,使boa 變小5、BOA的配置BOA 需要在/etc目錄下建立一個(gè)boa 目錄,里面放入BOA的主要配置文件boa.conf。在BOA源碼目錄下已有一個(gè)示例boa.conf,可以在其基礎(chǔ)上進(jìn)行修改。 (a)、Group 的修改修改 Group nogroup 為 Group 0 由于在/etc/group文件中沒(méi)有nogroup組,所以設(shè)成0。另外在/etc/passwd 中有nobody用戶(hù),所以User nobody不用修改。(注意如果沒(méi)有nobody 用戶(hù),也需要將User設(shè)成0)(b)、ScriptAlias 的修改指示CGI 腳本的存放位置。修改 ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ 為 ScriptAlias /cgi-bin/ /var/www/cgi-bin/ ScriptAlias /index.html /var/www/index.html 指示網(wǎng)頁(yè)存放的位置。(c)、ServerName 的設(shè)置修改 ServerName .here/ 為 ServerName .here/ 注意:該項(xiàng)默認(rèn)為未打開(kāi),執(zhí)行BOA會(huì)異常退出,提示“gethostbyname:No such file ordirectory”,所以必須打開(kāi)。其它默認(rèn)設(shè)置即可。 6、BOA 的運(yùn)行成功配置以后,還需要?jiǎng)?chuàng)建日志文件所在目錄/var/log/boa ,創(chuàng)建HTML 文檔的主目錄/var/www,將靜態(tài)網(wǎng)頁(yè)存入該目錄下(可以將主機(jī) /usr/share/doc/HTML/ 目錄下的index.html 文件和img 目錄復(fù)制到/var/www 目錄下),創(chuàng)建CGI 腳本所在錄 /var/www/cgi-bin ,將cgi 的腳本存放在該目錄下。另外還要將mime.types 文件復(fù)制/etc 目錄下,通??梢詮膌inux 主機(jī)的 /etc 目錄下直接復(fù)制即可。實(shí)際運(yùn)行時(shí),可以將index.html文件、img目錄和mime.types文件放到CF 卡目錄下,建立目錄后,拷貝至相應(yīng)目錄。制作run.sh:mkdir /etc/boacp /cf/boa/boa.conf /etc/boa/mkdir /var/logmkdir /var/log/boamkdir /var/wwwcp /cf/boa/index.html /var/www/cp -r /cf/boa/img /var/www/mkdir /var/www/cgi-bincp /cf/boa/mime.types /etc/cp /cf/boa/boa /./boa &啟動(dòng)瀏覽器,直接在瀏覽器中輸入07/,出現(xiàn)BOA TEST的歡迎網(wǎng)頁(yè)。靜態(tài)HTML調(diào)試成功。1.4.2 CGI 腳本測(cè)試為了測(cè)試剛才建立的BOA服務(wù)器是否正確,我們可以編寫(xiě)一個(gè)簡(jiǎn)單例程進(jìn)行測(cè)試。helloworld.c 程序就起這個(gè)作用,其內(nèi)容如下:#includeint main() printf(Content-type: text/htmlnn);printf(n); printf(BOA CGI TESTn);printf(n); printf(BOA CGI TESTn);printf(n);printf(n);exit(0); 編寫(xiě)完后進(jìn)行交叉編譯,得到的helloworld 拷貝到var/www/cgi-bin 目錄下。# arm-linux-gcc -o helloworld.cgi helloworld.c在瀏覽器中輸入22/cgi-bin/helloworld 可以看到BOA測(cè)試頁(yè)面,表示CGI 測(cè)試通過(guò)。1.5 HTML 網(wǎng)頁(yè)設(shè)計(jì)普通的HTML 頁(yè)面只能提供靜態(tài)的信息給用戶(hù),如果要實(shí)現(xiàn)網(wǎng)頁(yè)的交互僅靠HTML 是無(wú)能為力的。在一個(gè)完整的系統(tǒng)中,用戶(hù)提交信息輸入界面的好壞將影響到系統(tǒng)的成敗。好的輸入界面可以彌補(bǔ)系統(tǒng)設(shè)計(jì)上的某些缺陷,但如何才能設(shè)計(jì)一個(gè)好的輸入界面呢?HTML 中表單(FORM)在CGI 中是常見(jiàn)使用的輸入界面,雖然并不十分完美,但它的確是目前www中最強(qiáng)大的輸入工具。FORM是由一組相關(guān)聯(lián)的標(biāo)簽所組成,使用方法就像HTML 中的其他標(biāo)簽一樣。在FORM 中提供了多種輸入資料的工具,如文字輸入?yún)^(qū)(Text)、下拉式菜單(select)、復(fù)選框(CheckBox)、單選框(RadioButton)等等。就目前所定義的標(biāo)準(zhǔn)種,F(xiàn)ORM 的標(biāo)簽可以分為、以及三個(gè)大類(lèi)。我們來(lái)看看具體的程序?qū)崿F(xiàn),下面是一段HTML 表單:CGI LED test基于S3C2440 的Web 服務(wù)器的設(shè)計(jì)程序系統(tǒng)資源:s3c2440,16M Flash,32M SDRM,IP:0輸入要點(diǎn)亮的LED:輸入LED 狀態(tài):網(wǎng)頁(yè)中表單由字頭開(kāi)始,結(jié)束。其中action=/cgi-bin/cgi_led.cgi指明使用的CGI 程序名為cgi_led.cgi;method 屬性指定提交數(shù)據(jù)的方法(POST 還是GET),這里使用的是GET 方法。我們要實(shí)現(xiàn)的功能很簡(jiǎn)單,就是采集現(xiàn)場(chǎng)的LED的狀態(tài),并在網(wǎng)頁(yè)上輸出結(jié)果。在這個(gè)實(shí)例中我們提交了兩個(gè)數(shù)據(jù),一個(gè)是數(shù)據(jù)的名字是led,另一個(gè)數(shù)據(jù)的名字是status,它們的值由用戶(hù)在網(wǎng)頁(yè)中輸入。這里首先了解一下CGI 編碼的規(guī)則。其規(guī)則如下:不同域(變量值對(duì))之間用“&”分開(kāi);變量與值之間用“”連接;空格符用“”代替;任何特殊字符用“”接相應(yīng)的十六進(jìn)制ASCII 碼代替,最后形成的格式為:name1=value1&name2=value2%name3=value3 .1.6 CGI 程序設(shè)計(jì)CGI(Common Gateway Interface) 通用網(wǎng)關(guān)接口的簡(jiǎn)稱(chēng)。其主要的功能是在WWW環(huán)境下,從客戶(hù)端傳遞一些信息給WEB服務(wù)器,再由WEB服務(wù)器去啟動(dòng)所指定的程序來(lái)完成特定的工作。所以簡(jiǎn)單點(diǎn)說(shuō),CGI是一種通用的接口標(biāo)準(zhǔn)。CGI可以為我們提供許多HTML(HyperText Markup Language,超文本標(biāo)記語(yǔ)言)無(wú)法做到的功能。比如一個(gè)計(jì)算器、顧客表格的提交以及統(tǒng)計(jì)、搜索引擎、WEB 數(shù)據(jù)庫(kù)等等。用HTML是沒(méi)有辦法記住客戶(hù)的任何信息的。要把顧客的信息記錄在服務(wù)器的硬盤(pán)上,就要用到CGI。CGI是一種通用的接口標(biāo)準(zhǔn)。CGI程序就是符合這種接口標(biāo)準(zhǔn)的,運(yùn)行在WEB服務(wù)器上的程序。它的工作就是控制信息要求,產(chǎn)生并傳回所需的文件。CGI 由瀏覽器的輸入觸發(fā)這個(gè)程序。先看看瀏覽器瀏覽網(wǎng)頁(yè)是怎樣實(shí)現(xiàn)的。作為一個(gè)用戶(hù)首先在瀏覽器的地址欄中添加上要訪問(wèn)的主頁(yè)地址并回車(chē)觸發(fā)這個(gè)申請(qǐng)。瀏覽器將申請(qǐng)發(fā)送到服務(wù)器上。WEB服務(wù)器接收這些申請(qǐng)并根據(jù).htm 或.html 的后綴并認(rèn)識(shí)到這是HTML 文件。WEB服務(wù)器從當(dāng)前硬盤(pán)或內(nèi)存中讀取正確的HTML 文件,然后將它送回瀏覽器。HTML文件將被用戶(hù)的瀏覽器解釋并將結(jié)果顯示在用戶(hù)瀏覽器上。CGI程序可以用來(lái)在WEB內(nèi)加入動(dòng)態(tài)的內(nèi)容。通過(guò)接口,瀏覽器能夠發(fā)送一個(gè)可執(zhí)行應(yīng)用程序的HTTP請(qǐng)求,而不僅僅只是靜態(tài)的HTML文件。服務(wù)器運(yùn)行指定的應(yīng)用程序,這個(gè)應(yīng)用程序讀取與請(qǐng)求相關(guān)的信息,獲得請(qǐng)求傳過(guò)來(lái)的數(shù)值。例如使用者填寫(xiě)HTML表單提交了數(shù)據(jù),瀏覽器將這些數(shù)據(jù)發(fā)送到WEB服務(wù)器上。WEB服務(wù)器接收這些數(shù)據(jù)并根據(jù)客戶(hù)機(jī)指定的CGI程序把這些數(shù)據(jù)遞交給指定的CGI程序,并使CGI在服務(wù)器上運(yùn)行。CGI程序運(yùn)行結(jié)束,生成HTML頁(yè)面,WEB服務(wù)器把CGI程序運(yùn)行的結(jié)果送回用戶(hù)瀏覽器。HTML文件將會(huì)被用戶(hù)的瀏覽器解釋并將結(jié)果顯示在用戶(hù)瀏覽器上。CGI的基本工作情況如下圖所示:圖3.3 CGI工作流程示意圖WEB服務(wù)器與CGI 程序之間通過(guò)四種途徑進(jìn)行通信: 環(huán)境變量、命令行、標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。其中負(fù)責(zé)輸入的有環(huán)境變量、命令行和標(biāo)準(zhǔn)輸入。命令行只用于ISINDEX 查詢(xún),較少使用。環(huán)境變量存放服務(wù)器向CGI程序傳遞的一些運(yùn)行參數(shù), 比如REQUEST_METHOD表示用戶(hù)提出請(qǐng)求或提交數(shù)據(jù)的方法是GET 還是POST。方法(METHOD) 是HTTP中對(duì)命令的稱(chēng)呼。GET方法通過(guò)環(huán)境變量QUERY-STRING傳遞用戶(hù)提交的數(shù)據(jù)。經(jīng)過(guò)編碼的數(shù)據(jù)以問(wèn)號(hào)打頭追加在標(biāo)識(shí)CGI腳本地址的URL后一起傳給WEB服務(wù)器。服務(wù)器將其存于QUERYSTRING中,CGI 程序可以通過(guò)getenv( )函數(shù)來(lái)讀取。編碼數(shù)據(jù)除了表單數(shù)據(jù),還可以是直接調(diào)用CGI腳本時(shí)追加在URL 地址后面的參數(shù)。POST 方法則通過(guò)標(biāo)準(zhǔn)輸入( stdin) 傳遞提交數(shù)據(jù)。編碼了的表單數(shù)據(jù)獨(dú)立地傳送給WEB 服務(wù)器, CGI 程序從標(biāo)準(zhǔn)輸入中獲得,可以用getchar( ), sscanf( ) , fread( ) 等函數(shù)。要注意的是數(shù)據(jù)的長(zhǎng)度是通過(guò)讀取環(huán)境變量CONTENT_LENGTH 獲得的, 而不是通過(guò)文件尾標(biāo)識(shí)符來(lái)判斷。一般而言,要使用CGI 程序就必須在WEB網(wǎng)頁(yè)中遷入調(diào)用CGI 程序的代碼。通常的做法有三種,一是通過(guò)表單調(diào)用,二是通過(guò)超鏈接調(diào)用,三是通過(guò)SSI 調(diào)用。在3.5節(jié)中我們已經(jīng)闡述了網(wǎng)頁(yè)的設(shè)計(jì),在這里重點(diǎn)說(shuō)明使用表單調(diào)用CGI 程序的辦法。 我們來(lái)看看到底如何從GET表單收集數(shù)據(jù)到CGI 程序,下面給出了一個(gè)比較簡(jiǎn)單的C 源代碼:#include #include #include #include #include #include #include #include #define DEVICE_GPIODRV /dev/gpiosint main() int fd; int led; int status; char *data; if(fd=open(DEVICE_GPIODRV,O_RDONLY | O_NONBLOCK)0) printf(open device: %sn,DEVICE_GPIODRV); perror(can not open device); exit(1); printf(Content-type:ext/html;charset=gb2312nn);printf(n); printf(CGI LED DEMOn); printf(n); printf(CGI LED DEMO 1:0 led1 on 1:1 led1 offn); printf(n); data=getenv(QUERY_STRING); if(sscanf(data,led=%ld&status=%ld,&led,&status)!=2) printf( 請(qǐng)正確輸入); printf(); if(led3) printf(Please input 0=led=3!); printf(); if(status1) printf(Please input 0=status=1!); printf(); ioctl(fd,status,led); close(fd); printf(n); exit(0); 對(duì)于CGI程序來(lái)講,當(dāng)采用GET方式提交數(shù)據(jù)時(shí),用戶(hù)提交的數(shù)據(jù)放在環(huán)境變量QUERY_STRING中。CGI程序從環(huán)境變量QUERY_STRING獲得數(shù)據(jù)。為了解釋和執(zhí)行程序,CGI必須要分析(處理)這個(gè)字符串。當(dāng)你想從服務(wù)器獲得數(shù)據(jù)并且不改變服務(wù)器上的數(shù)據(jù)時(shí),應(yīng)該選用GET。但是用GET 方式提交時(shí),數(shù)據(jù)不經(jīng)過(guò)CGI編碼,而且數(shù)據(jù)長(zhǎng)度不能超過(guò)1K字節(jié)。否則只能用POST方式了。CGI 程序的任務(wù)大概有兩部分,輸入任務(wù)和輸出任務(wù)。輸入任務(wù)就是指獲取用戶(hù)提交數(shù)據(jù)的過(guò)程。輸入任務(wù)大概分以下幾個(gè)步驟:(1)首先從CGI 環(huán)境變量REQUESR_METHOD中獲取CGI程序的提交方式;(2)根據(jù)提交方式的不同取出變量名和變量值。如果是Get方式,從環(huán)境變量QUERY_STRING 中取出編碼數(shù)據(jù);如果是POST 方式,從標(biāo)準(zhǔn)輸入輸出中讀取相應(yīng)的字符串,讀取長(zhǎng)度有環(huán)境變量CONTENT_LENGTH 決定。(3)根據(jù)CGI 編碼規(guī)則取出字符串中的數(shù)據(jù)(變量名和變量值對(duì))。在輸入任務(wù)完成后,我們得到所有的變量名和變量值對(duì),而后就是輸出任務(wù)。輸出任務(wù)主要有三個(gè):(1)輸出HTTP 響應(yīng)的頭標(biāo)志。如printf(“Content-type:ext/htmlnn”);它告訴Web 服務(wù)器隨后的輸出是以HTML 文本形式輸出的。注意這個(gè)頭信息中有兩個(gè)換行符,這是因?yàn)閃EB服務(wù)器需要在實(shí)際的文本信息開(kāi)始之前先看見(jiàn)一個(gè)空行。(2)調(diào)用其它程序(如遠(yuǎn)的測(cè)量程序、設(shè)置參數(shù)的程序、或者查詢(xún)數(shù)據(jù)庫(kù)的程序)。(3)輸出CGI 程序執(zhí)行結(jié)果。表單提交數(shù)據(jù)測(cè)試了解了POST 和GET 兩種表單提交數(shù)據(jù)方式以及步驟后,下面進(jìn)行測(cè)試。GET方式:對(duì)于那些使用了屬性“METHOD=GET”的表單(或者沒(méi)有METHOD 屬性,這時(shí)候GET 是其缺省值),CGI 定義為:當(dāng)表單被發(fā)送到服務(wù)器端后,表單中的數(shù)據(jù)被保存在服務(wù)器上一個(gè)叫做QUERY_STRING的環(huán)境變量中。這種表單的處理相對(duì)簡(jiǎn)單,只要讀取環(huán)境變量就可以了。這一點(diǎn)對(duì)不同的語(yǔ)言有不同的做法。在C語(yǔ)言中,你可以用庫(kù)函數(shù)getenv(定義在標(biāo)準(zhǔn)庫(kù)函數(shù)stdlib中)來(lái)把環(huán)境變量的值作為一個(gè)字符串來(lái)存取。你可以在取得了字符串中的數(shù)據(jù)后,運(yùn)用一些小技巧進(jìn)行類(lèi)型的轉(zhuǎn)換,這都是比較簡(jiǎn)單的了。在CGI 程序中的標(biāo)準(zhǔn)輸出(output)(比如在C中的stdout文件流)也是經(jīng)過(guò)重定義了的。它并沒(méi)有在服務(wù)器上產(chǎn)生任何的輸出內(nèi)容,而是被重定向到客戶(hù)瀏覽器。這樣,如果編寫(xiě)一個(gè)C 的CGI 程序的時(shí)候,把一個(gè)HTML 文檔輸出到它的stdout 上,這個(gè)HTML 文檔會(huì)被在客戶(hù)端的瀏覽器中顯示出來(lái)。這也是CGI 程序的一個(gè)基本原理。上例中具體的C 語(yǔ)法就不多講了,我們來(lái)看看它作為CGI 程序所特殊的地方。前面已經(jīng)提到標(biāo)準(zhǔn)輸出的內(nèi)容就是要被顯示在瀏覽器中的內(nèi)容。第一行的輸出內(nèi)容是必須的,也是一個(gè)CGI 程序所特有的:printf(Content-type: ext/html;charset=gb2312nn),這個(gè)輸出是作為HTML 的文件頭。因?yàn)镃GI 不僅可以像瀏覽器輸出HTML 文本,而且可以輸出圖像,聲音之類(lèi)的東西。這一行告訴瀏覽器如何處理接受到的內(nèi)容。在Content-Type 的定義后面跟有兩行的空行,這也是不可缺少的。因?yàn)樗蠧GI 程序的頭部輸出都是相近的,因而可以為其定義一個(gè)函數(shù),來(lái)節(jié)省編程的時(shí)間。這是CGI 編程常用的一個(gè)技巧。程序在后面調(diào)用了用了庫(kù)函數(shù)getevn 來(lái)得到QUERY_STRING 的內(nèi)容,然后使用sscanf 函數(shù)把每個(gè)參數(shù)值取出來(lái),要注意的是sscanf 函數(shù)的用法。其他的就沒(méi)有什么了,和一般的C 程序沒(méi)有區(qū)別。把程序編譯后,改名為cgi_led.cgi 放在/cgi-bin/目錄下面,就可以被表單調(diào)用了。這樣,一個(gè)處理GET 方式表單的CGI 程序就大功告成了。POST方式:下面我們來(lái)考慮另外一種表單傳送方法。假設(shè)我們要實(shí)現(xiàn)的任務(wù)是這樣的:把表單中客戶(hù)輸入的一段文本內(nèi)容添加到服務(wù)器上的一個(gè)文本文件的后面。這可以看作是一個(gè)留言版程序的雛形。顯然,這個(gè)工作是無(wú)法用java script 這種客戶(hù)端腳本來(lái)實(shí)現(xiàn),也算得上真正意義上的CGI 程序了??雌饋?lái)這個(gè)問(wèn)題和上面講的內(nèi)容很相近,僅僅是用不同的表單和不同的腳本(程序)而已。但實(shí)際上,這中間是有一些區(qū)別的。在上面的例子中,GET 的處理方法可以看作是“純查詢(xún)(pure query)”類(lèi)型的,也就是說(shuō),它與狀態(tài)無(wú)關(guān)。同樣的數(shù)據(jù)可以被提交任意的次數(shù),而不會(huì)引起任何的問(wèn)題(除了服務(wù)器的一些小小的開(kāi)銷(xiāo))。但是現(xiàn)在的任務(wù)就不同了,至少它要改變一個(gè)文件的內(nèi)容。因而,可以說(shuō)它是與狀態(tài)有關(guān)的。這也算是POST 和GET 的區(qū)別之一。而且,GET 對(duì)于表單的長(zhǎng)度是有限制的,而POST 則不然,這也是在這個(gè)任務(wù)中選用POST 方法的主要原因。但相對(duì)的,對(duì)GET 的處理速度就要比POST 快一些。在CGI 的定義中,對(duì)于POST 類(lèi)型的表單,其內(nèi)容被送到CGI 程序的標(biāo)準(zhǔn)輸入(在C 語(yǔ)言中是stdin),而被傳送的長(zhǎng)度被放在環(huán)境變量CONTENT_LENGTH 中。因而我們要做的就是,在標(biāo)準(zhǔn)輸入中讀入CONTENT_LENGTH 長(zhǎng)度的字符串。從標(biāo)準(zhǔn)輸出讀入數(shù)據(jù)聽(tīng)起來(lái)似乎要比從環(huán)境變量中讀數(shù)據(jù)來(lái)的要容易一些,其實(shí)則不然,有一些細(xì)節(jié)地方要注意,這在下面的程序中可以看到。特別要注意的一點(diǎn)就是:CGI 程序和一般的程序有所不同,一般的程序在讀完了一個(gè)文件流的內(nèi)容之后,會(huì)得到一個(gè)EOF 的標(biāo)志。但在CGI 程序的表單處理過(guò)程中,EOF 是永遠(yuǎn)不會(huì)出現(xiàn)的,所以千萬(wàn)不要讀多于CONTENT_LENGTH 長(zhǎng)度的字符,否這會(huì)有什么后果,誰(shuí)也不知道(CGI 規(guī)范中沒(méi)有定義,一般根據(jù)服務(wù)器不同而有不同得處理方法)。我們來(lái)看看到底如何從POST 表單收集數(shù)據(jù)到CGI 程序,下面給出了一個(gè)比較簡(jiǎn)單的C 源代碼。#include #define MAXLEN 80 #define EXTRA 5 /* 4 個(gè)字節(jié)留給字段的名字data, 1 個(gè)字節(jié)留給= */ #define MAXINPUT MAXLEN+EXTRA+2 /* 1 個(gè)字節(jié)留給換行符,還有一個(gè)留給后面的NULL */ #define DATAFILE data.txt /* 要被添加數(shù)據(jù)的文件 */ void unencode(char *src, char *last, char *dest) for(; src != last; src+, dest+) if(*src = +) *dest = ; else if(*src = %) int code; if(sscanf(src+1, %2x, &code) != 1) code = ?; *dest = code; src +=2; else *dest = *src; *dest = ; *+dest = ; int main(void) char *lenstr;char inputMAXINPUT, dataMAXINPUT;long len; FILE *f;printf(Content-type: text/html;charset=gb2312nn);printf(n); printf(Responsen);printf(n); printf(Responsen);printf(n);lenstr = getenv(CONTENT_LENGTH);if(lenstr = NULL | sscanf(lenstr,%ld,&len)!=1 | len MAXLEN) printf(表單提交錯(cuò)誤); printf(); else fgets(input, len+1, stdin);unencode(input+EXTRA, input+len, data);f = fopen(DATAFILE, a);if(f = NULL)printf(對(duì)不起,意外錯(cuò)誤,不能夠保存你的數(shù)據(jù) ); printf(); else fputs(data, f); fclose(f); printf(非常感謝,您的數(shù)據(jù)已經(jīng)被保存%s,data); printf(); printf(n); exit(0); 從本質(zhì)上來(lái)看,程序先從CONTENT_LENGTH 環(huán)境變量中得到數(shù)據(jù)的字長(zhǎng),然后讀取相應(yīng)長(zhǎng)度的字符串。因?yàn)閿?shù)據(jù)內(nèi)容在傳輸?shù)倪^(guò)程中是經(jīng)過(guò)了編碼的,所以必須進(jìn)行相應(yīng)的解碼。編碼的規(guī)則很簡(jiǎn)單,主要的有這幾條:1、 表單中每個(gè)每個(gè)字段用字段名后跟等號(hào),再接上上這個(gè)字段的值來(lái)表示,每個(gè)字段之間的內(nèi)容用&連結(jié);2、 所有的空格符號(hào)用加號(hào)代替,所以在編碼碼段中出現(xiàn)空格是非法的;3、 特殊的字符比如標(biāo)點(diǎn)符號(hào),和一些有特定意義的字符如“+”,用百分號(hào)后跟其對(duì)應(yīng)的ACSII 碼值來(lái)表示。例如:如果用戶(hù)輸入的是:Hello there!那么數(shù)據(jù)傳送到服務(wù)器的時(shí)候經(jīng)過(guò)編碼,就變成了data=Hello+there%21 上面的unencode()函數(shù)就是用來(lái)把編碼后的數(shù)據(jù)進(jìn)行解碼的。在解碼完成后,數(shù)據(jù)被添加到data.txt 文件的尾部,并在瀏覽其中回顯出來(lái)。把文件編譯完成后,把它改名為collect.cgi 后放在CGI 目錄中就可以被表單調(diào)用了。下面給出了其相應(yīng)的表單: CGI POST test CGI POST test 請(qǐng)輸入您的留言(最多80 個(gè)字符): 事實(shí)上,這個(gè)程序只能作為例子,是不能夠正式的使用的。它漏掉了很關(guān)鍵的一個(gè)問(wèn)題:當(dāng)有多個(gè)用戶(hù)同時(shí)像文件寫(xiě)入數(shù)據(jù)是,肯定會(huì)有錯(cuò)誤發(fā)生。而對(duì)于一個(gè)這樣的程序而言,文件被同時(shí)寫(xiě)入的幾率是很大的。因此,在比較正式的留言版程序中,都需要做一些更多的考慮,比如加入一個(gè)信號(hào)量,或者是借助于一個(gè)鑰匙文件等。因?yàn)槟侵皇蔷幊痰募记蓡?wèn)題,在這兒就不多說(shuō)了。最后,我們來(lái)寫(xiě)一個(gè)瀏覽data.txt 文件的的CGI 程序,這只需要把內(nèi)容輸出到stdout 就可以了: #include #include #define DATAFILE ./data/data.txt int main(void) FILE *f = fopen(DATAFILE,r); int ch; if(f = NULL) printf(%s%c%c , Content-Type:text/html;charset=gb2312,13,10); printf(錯(cuò)誤 ); printf(意外錯(cuò)誤,無(wú)法打開(kāi)文件); else printf(%s%c%c , Content-Type:text/plain,13,10); while(ch=getc(f) != EOF) putchar(ch); fclose(f); return 0; 這個(gè)程序唯一要注意的是:它并沒(méi)有把data.txt 包裝成HTML 格式后再輸出,而是直接作為簡(jiǎn)單文本(plain text)輸出,這只要在輸出的頭部用text/plain 類(lèi)型代替text/html 就可以了,瀏覽器會(huì)根據(jù)Content-Type 的類(lèi)型自動(dòng)的選擇相應(yīng)的處理方法。1.7 設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)現(xiàn)在設(shè)計(jì)一個(gè)簡(jiǎn)單的LED 控制頁(yè)面。當(dāng)輸入1 /0時(shí)對(duì)應(yīng)的LED燈亮滅。LED 驅(qū)動(dòng)程序使用insmod命令加載,CGI 程序編譯后放在var/www/cgi-bin 目錄下。#include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME gpios#define GPIO_MAJOR 215static unsigned long gpio_table = S3C2410_GPD0, S3C2410_GPD1, S3C2410_GPD2, S3C2410_GPD3, ; static unsigned int gpio_cfg_table = S3C2410_GPD0_OUTP, S3C2410_GPD1_OUTP, S3C2410_GPD2_OUTP, S3C2410_GPD3_OUTP, ; static int sbc2440_gpios_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) switch(cmd) case 0: case 1: if (arg 4) return -EINVAL; s3c2410_gpio_setpin(gpio_tablearg, !cmd); return 0; default: return -EINVAL; static struct file_operations sbc2440_gpios_fops = .owner = THIS_MODULE, .ioctl = sbc2440_gpios_ioctl, ; static int
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 評(píng)價(jià)在學(xué)生個(gè)性化發(fā)展中的作用考核試卷
- 農(nóng)業(yè)機(jī)械循環(huán)經(jīng)濟(jì)政策研究考核試卷
- 觸感要求與手套的耐磨層設(shè)計(jì)關(guān)聯(lián)考核試卷
- 急性冠狀動(dòng)脈綜合征分級(jí)診療服務(wù)技術(shù)方案
- 停電事故應(yīng)急預(yù)案(21篇)
- 《哈利波特》讀后感范文
- 人生不應(yīng)放棄的演講稿
- 會(huì)計(jì)專(zhuān)業(yè)技術(shù)資格初級(jí)會(huì)計(jì)實(shí)務(wù)模擬試卷無(wú)答案
- 法制小衛(wèi)士活動(dòng)方案
- 法律營(yíng)銷(xiāo)活動(dòng)方案
- 2025年人教版小學(xué)五年級(jí)下冊(cè)數(shù)學(xué)期末重難點(diǎn)測(cè)評(píng)試題(含答案和解析)
- 2024年天津市應(yīng)急管理局招聘行政執(zhí)法專(zhuān)職技術(shù)檢查員筆試真題
- GB/T 23858-2009檢查井蓋
- GB/T 23331-2020能源管理體系要求及使用指南
- GB/T 13173-2021表面活性劑洗滌劑試驗(yàn)方法
- 小學(xué)45年級(jí)必背古詩(shī)課件
- QC基礎(chǔ)知識(shí)培訓(xùn)材料課件
- 從知溝到數(shù)字鴻溝課件
- 《企業(yè)員工培訓(xùn)國(guó)內(nèi)外文獻(xiàn)綜述》4800字
- 客戶(hù)確認(rèn)單(標(biāo)準(zhǔn)模版)
- 船舶修理92黃本
評(píng)論
0/150
提交評(píng)論