1. 程式人生 > >樹莓派WEB伺服器(Boa)CGI程式設計入門

樹莓派WEB伺服器(Boa)CGI程式設計入門

通過上一個課程“Boa基本設定與使用”的學習,大家在樹莓派上應已經會安裝、配置、執行Boa伺服器,並且訪問到伺服器上的一個靜態網頁。
這不是執行Web伺服器最終的目的,最終應是通過B/S(瀏覽器/伺服器)模式實現兩端的相互。

下面通過一個CGI程式設計例項來學習,WEB伺服器的動態程式設計技術。“體重指數(BMI)計算器”,使用者輸入自己的身高與體重後點擊計算,伺服器就會計算出BMI數值。

體重指數(BMI)計算器

這裡寫圖片描述

開發設計流程

Created with Raphaël 2.1.0介面功能設計 靜態html檔案,html程式顯示介面靜態cgi檔案,cgi程式顯示介面
動態cgi檔案,cgi程式處理使用者資料顯示除錯執行

一、HTML靜態顯示

1 . 靜態的html檔案

cgi.html

<html>
<body>
<div align="center">

<form action="bmi.cgi" method="GET">

<table> 
<tr><td rowspan="3"><img src="bmi.png" hight="60" width="120"></td>
<td align="center" colspan
="3">
<h2>體重指數(BMI)計算器</h2></td></tr> <tr><td >身高 : <input type="text" name="cm" size="3"> cm </td> <td >體重 : <input type="text" name="kg" size="3"> kg </td> <td align="center" ><input type=submit value=" 計 算 " size="16"> </td
>
</tr> <tr><td align="center" colspan="3">BMI = <input type="text" name="ret" value="" size="3" readonly></tr> </table> </form> </br><img src=bmi_index.png > </div> </body> </html>

二、CGI程式輸出頁面

CGI基本概念

CGI:通用閘道器介面(Common Gateway Interface)是一個Web伺服器主機提供資訊服務的標準介面。通過CGI介面,Web伺服器就能夠獲取客戶端提交的資訊,轉交給伺服器端的CGI程式進行處理,最後返回結果給客戶端。

WEB伺服器和CGI程式之間的通訊
伺服器和CGI程式之間是通過標準輸入輸出來進行資料傳遞的,而這個過程需要環境變數的協作方可實現。

1.伺服器將URL指向一個應用程式
2.伺服器為應用程式執行做準備
3.應用程式執行,讀取標準輸入和有關環境變數
4.應用程式進行標準輸出

這裡寫圖片描述

伺服器上執行的cgi 通過標準輸入(環境變數)來取得客戶端使用者資料,通過標準輸出向客戶端返回資料顯示。

CGI資料輸出
CGI程式如何將資訊處理結果返回給客戶端?這實際上是CGI格式化輸出。
在CGI程式中的標準輸出stdout是經過重定義了的,它並沒有在伺服器上產生任何的輸出內容,而是被重定向到客戶瀏覽器,這與它是由C,還是Perl或Python實現無關。
所以,我們可以用列印來實現客戶端新的HTML頁面的生成。比如,C的printf是向該程序的標準輸出傳送資料,Perl和Python用print向該程序的標準輸出傳送資料。

課程中CGI程式使用C語言程式設計。
向標準輸出傳送網頁內容時要遵守MIME格式規則:
任意輸出前面必須有一個用於定義MIME型別的輸出內容(Content-type)行,而且隨後還必須跟一個空行。

printf( "Content-type:text/html\n\n" );

2 . cgi顯示介面程式

bmi.c

#include<stdio.h>

int main()
{
    printf( "Content-type:text/html\n\n" ); 

    printf("<html><body><div align=\"center\">\n");

    printf("<form action=\"bmi.cgi\" method=\"GET\"><table>     \n");

    printf("<tr><td rowspan=\"3\"><img src=\"../bmi.png\" hight=\"60\" width=\"120\"></td>    \n");
    printf("<td align=\"center\" colspan=\"3\"><h2>體重指數(BMI)計算器</h2></td></tr>    \n");
    printf("<tr><td >身高 : <input type=\"text\" name=\"cm\"  size=\"3\"> cm </td>    \n");
    printf("<td >體重 : <input type=\"text\" name=\"kg\"  size=\"3\"> kg </td>    \n");
    printf("<td align=\"center\" ><input type=submit value=\" 計 算 \" size=\"16\">   </td></tr>    \n");
    printf("<tr><td align=\"center\" colspan=\"3\">BMI =     \n");
    printf("<input type=\"text\" name=\"ret\" value=\" \"  size=\"3\" readonly></tr>     \n");
    printf("</table></form></br><img src=\"../bmi_index.png\" >    \n");
    printf("</div></body>   </html>     \n");

    return 0;                       

}

CGI程式的編譯執行

 $gcc bmi.c -o bmi.cgi           //gcc編譯器編譯
 $cp bmi.cgi /var/www/cgi-bin/   //拷貝到boa伺服器設定的cgi-bin目錄

 //在客戶端瀏覽器輸入cgi程式地址如:10.1.1.123/cgi-bin/bmi.cgi 回車後就可看到本文最開始顯示的web頁面。

三、CGI程式資料處理

CGI環境變數
對於CGI程式來說,它繼承了系統的環境變數。CGI環境變數在CGI程式啟動時初始化,在結束時銷燬。
當一個CGI程式不是被HTTP伺服器呼叫時,它的環境變數幾乎是系統環境變數的複製。當這個CGI程式被HTTP伺服器呼叫時,它的環境變數就會多了關於HTTP伺服器、客戶端、CGI傳輸過程等專案。

這裡寫圖片描述

CGI資料傳輸方式
REQUEST_METHOD:它的值一般包括兩種:POST和GET,但我們寫CGI程式時,最後還要考慮其他的情況。
1.POST方法
如果採用POST方法,那麼客戶端來的使用者資料將存放在CGI程序的標準輸入中,同時將使用者資料的長度賦予環境變數中的CONTENT_LENGTH。
2.GET方法
在該方法下,CGI程式無法直接從伺服器的標準輸入中獲取資料,因為伺服器把它從標準輸入接收到得資料編碼到環境變數QUERY_STRING(或PATH_INFO)。
3.POST與GET的區別
以 GET 方式接收的資料是有長度限制,而用 POST 方式接收的資料是沒有長度限制的。並且,以 GET 方式傳送資料,可以通過 URL 的形式來發送,但 POST方式傳送的資料必須要通過 Form 才到傳送。

CGI程式實現步驟
從伺服器獲取資料
C語言實現程式碼:
POST方法
length = atoi(getenv(“CONTENT_LENGTH”));
inputstring = malloc(sizeof(char)*length + 1);
fread(inputstring, sizeof(char), length, stdin);

GET方法
inputstring = getenv(“QUERY_STRING”);

CGI程式獲取資料都是連續字串要進行解析才能得到獨立資料。
getvalue.h檔案中給出處理函式get_value( )

3 . cgi資料動態處理程式

在上面bmi.c基礎上進行修改,首先在main函式最前面加上以下程式碼。

int main(){
    char *val_cm = NULL;
    char *val_kg = NULL;
    int cm,kg,len=0;
    float mm,bmi=0.0;

    set_env(getenv("REQUEST_METHOD"),
            getenv("CONTENT_LENGTH"),
            getenv("QUERY_STRING"));    

    //<input type="text" name="cm"  size="3">       
    val_cm = get_value("cm");   //通過變數名獲取身高

    val_kg = get_value("kg");   //通過變數名獲取體重 
    cm = atoi(val_cm);
    kg = atoi(val_kg);
    if(cm > 0 && kg > 0){
        mm = cm/100.0;
        bmi = (kg / (mm * mm));
    }
...
//這裡是頁面顯示程式碼
...
}

下面輸出bmi資料的html程式碼。

printf("<input type=\"text\" name=\"ret\" value=\" \"  size=\"3\" readonly></tr>     \n");

修改成輸出計算出使用者資料的程式碼。

if(bmi == 0.0)
    printf("<input type=\"text\" name=\"ret\" value=\"  \"  size=\"3\" readonly></tr>     \n");
else
      printf("<input type=\"text\" name=\"ret\" value=\" %4.2f  \"  size=\"3\" readonly></tr>     \n",bmi); 

編譯後copy到cgi-bin目錄,現在使用者在瀏覽器就可以輸入資料提交後,伺服器計算結果顯示。

如果瀏覽器出現502錯誤,說明 cgi程式執行有問題。可以在終端下執行除錯。