嵌入式WEB服務器BOA.conf詳解和CGI(實例)

嵌入式WEB服務器BOA和CGI
嵌入式WEB服務器常見的有
lighttpd 
shttpd 
thttpd
boa 
mathopd 
minihttpd
appweb
goahead
========================================================================
嵌入式WEB服務器BOA的移植方法(一)2007-2-26 16:20:00
  隨着Internet技術的興起,在嵌入式設備的管理與交互中,基於Web方式的應用成爲目前的主流,
這種程序結構也就是大家非常熟悉的B/S結構,即在 嵌入式設備上運行一個支持腳本或CGI功能的Web服務器,
能夠生成動態頁面,在用戶端只需要通過Web瀏覽器就可以對嵌入式設備進行管理和監控,非常方 便實用。
本節主要介紹這種應用的開發和移植工作。
用戶首先需要在嵌入式設備上成功移植支持腳本或CGI功能的Web服務器,然後才能進行應用程序的開發。
    1、 嵌入式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目錄下。
===================================================================
 
===================host test=======================================
1.進入 boa-0.94.13/src
 ./configure 
 make
2.在etc/下建立boa目錄並將boa.conf拷貝到該目錄下.更改boa.conf 
      Group nogroup  ===》Group 0
3.在 /var/log/下建立boa目錄,該目錄下可以查看boa服務器的日誌
4.其它的一些路徑
默認是/var/www下的內容可以訪問                       (DocumentRoot /var/www)
默認cgi :ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/  (cgi可執行程序放在 /usr/lib/cgi-bin/目錄下)
 例子http://201.201.201.249/cgi-bin/cgi-test.cgi
CGIPath /bin:/usr/bin:/usr/local/bin
 只有這些目錄下的命令可以被調用,如果要root的權限(如ifconfig配置ip)需要加上/sbin
 
 
 
=====================================================================
cgi例子
=====================================================================
//pass.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* getcgidata(FILE* fp, char* requestmethod);
int main()
{
       char *input;
       char *req_method;
       char name[64];
       char pass[64];
       int i = 0;
       int j = 0;
      
//     printf("Content-type: text/plain; charset=iso-8859-1\n\n");
       printf("Content-type: text/html\n\n");
       printf("The following is query reuslt:<br><br>");

       req_method = getenv("REQUEST_METHOD");
       input = getcgidata(stdin, req_method);

       // 我們獲取的input字符串可能像如下的形式
       // Username="admin"&Password="aaaaa"
       // 其中"Username="和"&Password="都是固定的
       // 而"admin"和"aaaaa"都是變化的,也是我們要獲取的
      
       // 前面9個字符是UserName=
       // 在"UserName="和"&"之間的是我們要取出來的用戶名
       for ( i = 9; i < (int)strlen(input); i++ )
       {
              if ( input[i] == '&' )
              {
                     name[j] = '\0';
                     break;
              }                  
              name[j++] = input[i];
       }

       // 前面9個字符 + "&Password="10個字符 + Username的字符數
       // 是我們不要的,故省略掉,不拷貝
       for ( i = 19 + strlen(name), j = 0; i < (int)strlen(input); i++ )
       {
              pass[j++] = input[i];
       }
       pass[j] = '\0';

       printf("Your Username is %s<br>Your Password is %s<br> \n", name, pass);
      
       return 0;
}

char* getcgidata(FILE* fp, char* requestmethod)
{
       char* input;
       int len;
       int size = 1024;
       int i = 0;
      
       if (!strcmp(requestmethod, "GET"))
       {
              input = getenv("QUERY_STRING");
              return input;
       }
       else if (!strcmp(requestmethod, "POST"))
       {
              len = atoi(getenv("CONTENT_LENGTH"));
              input = (char*)malloc(sizeof(char)*(size + 1));
             
              if (len == 0)
              {
                     input[0] = '\0';
                     return input;
              }
             
              while(1)
              {
                     input[i] = (char)fgetc(fp);
                     if (i == size)
                     {
                            input[i+1] = '\0';
                            return input;
                     }
                    
                     --len;
                     if (feof(fp) || (!(len)))
                     {
                            i++;
                            input[i] = '\0';
                            return input;
                     }
                     i++;
                    
              }
       }
       return NULL;
}
 
 
/*
*  gcc -o pass.cgi pass.c
*/
//pass.html
<html>
<head><title>用戶登陸驗證</title></head>
<body>
<form name="form1" action="/cgi-bin/pass.cgi" method="POST">
<table align="center">
    <tr><td align="center" colspan="2"></td></tr>
    <tr>
       <td align="right">用戶名</td>
       <td><input type="text" name="Username"></td>
    </tr>
    <tr>
       <td align="right">密&nbsp;&nbsp;碼</td>
       <td><input type="password" name="Password"></td>
    </tr>
    <tr>
       <td><input type="submit" value="登  錄"></td>
       <td><input type="reset" value="取  消"></td>
    </tr>
</table>
</form>
</body>
</html>

本文轉載自網絡文章!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章