boa cgi html

隨着Internet技術的興起,在嵌入式設備的管理與交互中,基於Web方式的應用成爲目前的主流,這種程序結構也就是你們很是熟悉的B/S結構,即在嵌入式設備上運行一個支持腳本或CGI功能的Web服務器,可以生成動態頁面,在用戶端只須要經過Web瀏覽器就能夠對嵌入式設備進行管理和監控,很是方便實用。本節主要介紹這種應用的開發和移植工做。

   用戶首先須要在嵌入式設備上成功移植支持腳本或CGI功能的Web服務器,而後才能進行應用程序的開發。
   
一、嵌入式Web服務器移植  
   
   因爲嵌入式設備資源通常都比較有限,而且也不須要能同時處理不少用戶的請求,所以不會使用Linux下最經常使用的如Apache等服務器,而須要使用一些專門爲嵌入式設備設計的Web服務器,這些Web服務器在存貯空間和運行時所佔有的內存空間上都會很是適合於嵌入式應用場合。
   典型的嵌入式Web服務器有Boa (www.boa.org)和thttpd (http://www.acme.com/software/thttpd/)等,它們和Apache等高性能的Web服務器主要的區別在於它們通常是單進程服務器,只有在完成一個用戶請求後才能響應另外一個用戶的請求,而沒法併發響應,但這在嵌入式設備的應用場合裏已經足夠了。
   
   咱們介紹比較經常使用的Boa服務器的移植。Boa是一個很是小巧的Web服務器,可執行代碼只有約60KB。它是一個單任務Web服務器,只能依次完成用戶的請求,而不會fork出新的進程來處理併發鏈接請求。但Boa支持CGI,可以爲CGI程序fork出一個進程來執行。Boa的設計目標是速度和安全,在其站點公佈的性能測試中,Boa的性能要好於Apache服務器。
    第一步完成Boa程序的移植。從www.boa.org下載Boa源碼,當前最新版本爲0.94.13,將其解壓並進入源碼目錄的src子目錄
    # tar xzf boa-0.94.13.tar.gz
    # cd boa-0.94.13/src
生成Makefile文件
    # ./configure
    修改Makefile文件,找到CC=gcc,將其改爲CC = arm-linux-gcc,再找到CPP = gcc –E,將其改爲CPP = arm-linux-gcc –E,並保存退出。
    而後運行make進行編譯,獲得的可執行程序爲boa,將調試信息剝去,獲得的最後程序只有約60KB大小。
    # make
    # arm-linux-strip boa
   第二步完成Boa的配置,使其可以支持CGI程序的執行。Boa須要在/etc目錄下創建一個boa目錄,裏面放入Boa的主要配置文件boa.conf。在Boa源碼目錄下已有一個示例boa.conf,能夠在其基礎上進行修改,下面解釋一下該文件的含義:
#監聽的端口號,缺省都是80,通常無需修改
Port 80
# bind調用的IP地址,通常註釋掉,代表綁定到INADDR_ANY,通配於服務器的全部IP地址
#Listen 192.68.0.5
#做爲哪一個用戶運行,即它擁有該用戶的權限,通常都是nobody,需
要 /etc/passwd中有nobody用戶
User nobody
#做爲哪一個用戶組運行,即它擁有該用戶組的權限,通常都是nogroup,須要在/etc/group文件中有nogroup組
Group nogroup
#當服務器發生問題時發送報警的email地址,目前未用,註釋掉
#ServerAdmin root@localhost
#錯誤日誌文件。若是沒有以/開始,則表示從服務器的根路徑開始。若是不須要錯誤日誌,則用#/dev/null。
在下面設置時,注意必定要創建/var/log/boa目錄
ErrorLog /var/log/boa/error_log
#訪問日誌文件。若是沒有以/開始,則表示從服務器的根路徑開始。若是不須要錯誤日誌,則用#/dev/null或直接註釋掉。
在下面設置時,注意必定要創建/var/log/boa目錄
#AccessLog /var/log/boa/access_log
#是否使用本地時間。若是沒有註釋掉,則使用本地時間。註釋掉則使用UTC時間
#UseLocaltime
#是否記錄CGI運行信息,若是沒有註釋掉,則記錄,註釋掉則不記錄
#VerboseCGILogs
#服務器名字
ServerName www.hyesco.com
#是否啓動虛擬主機功能,即設備能夠有多個網絡接口,每一個接口均可以擁有一個虛擬的Web服務器。通常註釋掉,即不須要啓動
#VirtualHost
#很是重要,HTML文檔的主目錄。若是沒有以/開始,則表示從服務器的根路徑開始。
DocumentRoot /var/www
#若是收到一個用戶請求的話,在用戶主目錄後再增長的目錄名
UserDir public_html
#HTML目錄索引的文件名,也是沒有用戶只指明訪問目錄時返回的文件名
DirectoryIndex index.html
#當HTML目錄沒有索引文件時,用戶只指明訪問目錄時,boa會調用該程序生成索引文件而後返回給用戶,由於該過程比較慢最好不執行,能夠註釋掉或者給每一個HTML目錄加上DirectoryIndex指明的文件
#DirectoryMaker /usr/lib/boa/boa_indexer
#若是DirectoryIndex不存在,而且DirectoryMaker被註釋,那麼就用Boa自帶的索引生成程序來生成目錄的索引文件並輸出到下面目錄,該目錄必須是Boa能讀寫
# DirectoryCache /var/spool/boa/dircache
#一個鏈接所容許的HTTP持續做用請求最大數目,註釋或設爲0都將關閉HTTP持續做用
KeepAliveMax 1000
#HTTP持續做用中服務器在兩次請求之間等待的時間數,以秒爲單位,超時將關閉鏈接
KeepAliveTimeout 10
#指明mime.types文件位置。若是沒有以/開始,則表示從服務器的根路徑開始。能夠註釋掉避免使用mime.types文件,此時須要用AddType在本文件裏指明
MimeTypes /etc/mime.types
#文件擴展名沒有或未知的話,使用的缺省MIME類型
DefaultType text/plain
#提供CGI程序的PATH環境變量值
CGIPath /bin:/usr/bin:/usr/local/bin
#將文件擴展名和MIME類型關聯起來,和mime.types文件做用同樣。若是用mime.types
#文件,則註釋掉,若是不使用mime.types文件,則必須使用
#AddType application/x-httpd-cgi cgi
#指明文檔重定向路徑
#Redirect /bar http://elsewhere/feh/bar
#爲路徑加上別名
Alias /doc /usr/doc
#很是重要,指明CGI腳本的虛擬路徑對應的實際路徑。通常全部的CGI腳本都要放在實際路徑裏,用戶訪問執行時輸入站點+虛擬路徑+CGI腳本名
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
   用戶能夠根據本身須要,對boa.conf進行修改,但必需要保證其餘的輔助文件和設置必須和boa.conf裏的配置相符,否則Boa就不能正常工做。在上面的例子中,咱們還須要建立日誌文件所在目錄/var/log/boa,建立HTML文檔的主目錄/var/www,將mime.types文件拷貝到/etc目錄,建立CGI腳本所在目錄/var/www/cgi-bin/。mime.types文件用來指明不一樣文件擴展名對應的MIME類型,通常能夠直接從Linux主機上拷貝一個,大部分也都是在主機的/etc目錄下。
第三步就是測試Boa可否正常工做,靜態HTML頁面可否正常訪問,CGI腳本可否正常運行,通常採用NFS方式來進行測試工做,能夠將嵌入式目標系統上的/etc目錄拷貝到主機的NFS共享目錄下,而後將NFS共享目錄下的etc目錄從新NFS mount爲目標系統上的/etc目錄。這樣就能夠在主機上對etc目錄下的各類配置文件,如進行修改而馬上在目標系統上生效。
  假設主機/nfs目錄爲共享目錄,在其下面創建一個www子目錄做爲Web站點的主目錄,其內容以下:
# ls /nfs/www
cgi-bin  images index.html
   index.html爲測試主頁面,images爲存放各類圖片的子目錄,cgi-bin爲CGI腳本的存放目錄。根據示例boa.conf的配置,目前HTML文檔的主目錄爲/var/www,CGI腳本目錄爲/var/www/cgi-bin,則運行如下命令將主機的/nfs/www目錄mount成目標板上的/var/www目錄。而後就能夠運行boa了:
# mount -t nfs 192.168.0.20:/nfs/www /var/www -o nolock
# boa
在工做站上運行瀏覽器進行測試,在地址欄輸入目標系統IP,即
http://192.168.0.162
,能夠看到相關頁面,表示靜態HTML頁面測試經過。
    接下來進行CGI腳本的測試,咱們須要一個測試用的CGI腳本。能夠寫個最簡單的Hello World程序,示例代碼以下
#include
void main() {
    printf("Content-type: text/html\n\n") ;
    printf("\n") ;
    printf("CGI Output\n") ;
    printf("\n") ;
    printf("Hello, world.\n") ;
    printf("\n") ;
    printf("\n") ;
    exit(0) ;
}
   而後進行交叉編譯,將獲得的helloworld.cgi拷貝到主機的/nfs/www/cgi-bin目錄下。
#arm-linux-gcc -o helloworld.cgi helloworld.c
#cp helloworld.cgi /nfs/www/cgi-bin
在瀏覽器地址欄輸入http://192.168.67.16/cgi-bin/helloworld.cgi,能夠看到相關頁面,表示CGI腳本測試經過。
  如今咱們已經可讓Boa在嵌入式目標系統上正常工做了,嵌入式Web服務器移植成功。在以上的移植過程當中,最好設定boa.conf中的錯誤日誌文件ErrorLog,容許Boa記錄錯誤信息;測試靜態HTML頁面和CGI腳本時,無論結果如何,最好都查看錯誤日誌文件;CGI腳本測試很容易發生權限不夠的錯誤,要保證Boa訪問的主目錄、CGI腳本目錄以及臨時文件目錄(若是沒有設置TMP環境變量時,缺省是/tmp目錄),都必須能被Boa運行時所表明的用戶徹底訪問,該用戶由boa.conf中的User指出。


   目前Web技術中生成動態Web頁面的方法有CGI和服務器腳本,如JSP, ASP等,但後者須要Web服務器具備這些腳本的運行支持模塊。在嵌入式Web服務器中,考慮到資源限制問題,通常都只提供CGI支持,所以在嵌入式設備中Web方式應用實際上就是基於CGI的程序開發。
    CGI(Common Gate Intergace)是一段運行在Web服務器上的程序,提供同客戶端Html頁面的接口。咱們看一個實際例子:常見的我的主頁上大都有一個留言本,留言本的工做方式是這樣的:先由用戶輸入一些信息,如名字之類的東西,接着用戶按一下「留言」(到目前爲止工做都在客戶端),瀏覽器就把這些信息傳送到服務器的CGI程序中,因而CGI程序在服務器上按照預約的方法進行處理,在本例中就是把用戶提交的信息存入指定的文件中,最後CGI程序給客戶端發回一個「留言結束」字樣的頁面,用戶能夠在瀏覽器裏看到。
  在進行CGI編程以前,咱們先了解HTML的一些知識。CGI可使用多種編程語言來實現,包括C、 C++、Perl等,但在嵌入式設備的開發中,通常都不會採用Perl等解釋性語言,由於這種語言還須要有解釋執行的支撐模塊,會佔用存貯空間和內存,最經常使用的方法固然是用C來編寫,但C並非很適合開發象CGI這種須要大量進行字符串操做的程序,編程比較煩瑣,所以,對於一個專業的開發人員來講,首先想到的應該是有沒有可複用的庫來支持快速高效的開發CGI程序。幸運的是目前就有很多開放源碼的支持CGI開發的 C庫。咱們在此只介紹CGIC,有興趣的朋友能夠本身在Internet上搜索其餘的C庫。
CGIC庫的移植
   

   CGIC是一個支持CGI開發的開放源碼的標準C庫,能夠無償使用,只須要在開發的站點和程序文檔中有個公開聲明便可,代表程序使用了CGIC庫,用戶也能夠購買商業受權而無需公開聲明。
    CGIC可以提供如下功能:
   1  分析數據,並自動校訂一些有缺陷的瀏覽器發來的數據;
   2  透明接收用GET或 POST方法發來的From數據;
   3   能接受上傳文件;
   4   可以設置和接收cookies;
   5   用一致的方式處理From元素裏的回車;
   6   提供字符串,整數,浮點數,單選或多選功能來接收數據;
   7   提供數字字段的邊界檢查;
   8   可以將CGI環境變量轉化成C中的非空字符串;
   9   提供CGI程序的調試手段,可以回放CGI程序執行時的CGI狀態;
  總之,CGIC是一個功能比較強大的支持CGI開發的標準C庫,並支持Linux, Unix 和Windows等多操做系統。
  如下描述CGIC的移植過程。
  從CGIC的主站點http://www.boutell.com/cgic/下載源碼,當前最新版本是2.05版。將其解壓並進入源碼目錄
    # tar xzf cgic205.tar.gz

    # cd cgic205

   
修改Makefile文件,找到CC=gcc,將其改爲CC=arm-linux-gcc,找到AR=ar,將其改爲AR=arm-linux-ar,找到RANLIB=ranlib,將其改爲RANLIB=arm-linux-ranlib。找到gcc cgictest.o -o cgictest.cgi ${LIBS},將其改爲$(CC) $(CFLAGS) cgictest.o -o cgictest.cgi ${LIBS},找到gcc capture.o -o capture ${LIBS},將其改爲$(CC) $(CFLAGS) capture.o -o capture ${LIBS},並保存退出。    而後運行make進行編譯,獲得的CGIC庫libcgic.a,咱們經過調試輔助程序capture和測試程序cgictest.cgi,來驗證生成CGIC庫的正確性。    將capture和cgictest.cgi拷貝到主機的/nfs/www/cgi-bin目錄下。     在工做站的瀏覽器地址欄輸入http://192.168.67.16/cgi-bin/cgictest.cgi,能夠看到頁面,表示CGIC庫和測試腳本都移植成功。cgictest.cgi比較完整的展示了CGIC庫的功能,在開發基於CGIC庫的CGI程序前最好先掌握cgictest.cgi程序,也是用戶開發特定應用程序時的參考範例。   HTML模板的製做 Web方式的應用開發通常都會將界面和程序邏輯脫離開來,容許在必定程度下更改界面,如改變界面文本的屬性,創建多語言版本等,而無需改動程序邏輯。界面通常由美工來進行製做,而程序員負責具體功能的實現。在 HTML中,表單 (FORM)是最主要的傳遞信息的手段,它適用於任何瀏覽器。表單中有不少元素,包括輸入文本框,單選框,多選框,按鈕,等等,能夠提供信息的交互。具體對象說明和語法請參見其餘HTML書籍,在這裏不做介紹。根據應用需求,美工或其餘設計人員將最後的Web頁面設計出來,做爲程序員進行開發的模板。     CGI程序的工做通常就是接收表單數據,進行數據處理,最後根據處理結果生成新的頁面返回給瀏覽器。表單數據通常是以POST方法提交給服務器,由CGI程序得到,程序必需要將界面數據和內部數據對應起來纔可以進行下一步的處理。CGI程序從頁面獲取數據就根據元素名字/值中的元素名字來進行區分。但CGI返回頁面就比較麻煩。因爲界面在程序開發完成後還有可能會改變,並且有些須要程序處理的地方可能沒有表單元素,所以對程序來講,不能以表單元素名做爲區分的基礎,通常方法是採用HTML中的註釋來標記。     程序員須要在模板中爲每個表單元素以及其餘任何須要程序處理的地方,按照必定規則,如註釋的下一行就是表單元素行,創建其註釋標記。CGI程序就能夠根據註釋標記來判斷表單元素信息並進行處理。程序逐行讀取模板文件,檢查有無註釋標記,若有的話,則下一行須要進行處理,給表單元素賦上數據,最後就能夠返回帶數據的頁面給瀏覽器。     HTML模板還須要關注的是輸入的檢查。根據輸入檢查越早越好的原則,須要在用戶界面上就對用戶提交的數據進行檢查。目前通常是採用javascript腳本的方式。當用戶提交數據時,表單對象的onSubmit方法就會被調用,在該方法裏就能夠對用戶的輸入進行檢查。經常使用的檢查有是否必需、最大/小長度、是否字符、是否數字、email地址、IP地址是否正確、是否匹配一個正則表達式等。 CGI程序的開發     CGI程序的工做通常就是接收表單數據,根據應用需求進行數據處理,最後根據處理結果生成新的頁面返回給瀏覽器。表單數據通常是以POST方法提交給服務器,由CGI程序得到,程序根據元素名字/值中的元素名字來區分數據,完成數據處理後,再讀取相應的模板文件,根據註釋標記將對應的數據填充到HTML文本中去,生成最後的頁面返回給瀏覽器。     程序通常邏輯爲:     1.  安全性檢查,是否容許運行腳本;     2.  處理用戶提交的數據,根據元素名字/值中的元素名字來區分數據,而後根據應用需求進行數據處理;     3.  將處理結果填充表單,根據註釋標記將對應的數據填充到HTML文本中去,生成最後的頁面返回給瀏覽器。     關於具體的代碼實現細節,用戶能夠參考《嵌入式Linux系統開發詳解-基於EP93XX系列ARM》一書的相關章節。(全文完)