C++ Web 編程

2022-06-13 15:27 更新

C++ Web 編程

什么是 CGI?

  • 公共網(wǎng)關(guān)接口(CGI),是一套標(biāo)準(zhǔn),定義了信息是如何在 Web 服務(wù)器和客戶端腳本之間進(jìn)行交換的。
  • CGI 規(guī)范目前是由 NCSA 維護(hù)的,NCSA 定義 CGI 如下:
  • 公共網(wǎng)關(guān)接口(CGI),是一種用于外部網(wǎng)關(guān)程序與信息服務(wù)器(如 HTTP 服務(wù)器)對(duì)接的接口標(biāo)準(zhǔn)。
  • 目前的版本是 CGI/1.1,CGI/1.2 版本正在推進(jìn)中。

Web 瀏覽

為了更好地了解 CGI 的概念,讓我們點(diǎn)擊一個(gè)超鏈接,瀏覽一個(gè)特定的網(wǎng)頁或 URL,看看會(huì)發(fā)生什么。

  • 您的瀏覽器聯(lián)系上 HTTP Web 服務(wù)器,并請(qǐng)求 URL,即文件名。
  • Web 服務(wù)器將解析 URL,并查找文件名。如果找到請(qǐng)求的文件,Web 服務(wù)器會(huì)把文件發(fā)送回瀏覽器,否則發(fā)送一條錯(cuò)誤消息,表明您請(qǐng)求了一個(gè)錯(cuò)誤的文件。
  • Web 瀏覽器從 Web 服務(wù)器獲取響應(yīng),并根據(jù)接收到的響應(yīng)來顯示文件或錯(cuò)誤消息。

然而,以這種方式搭建起來的 HTTP 服務(wù)器,不管何時(shí)請(qǐng)求目錄中的某個(gè)文件,HTTP 服務(wù)器發(fā)送回來的不是該文件,而是以程序形式執(zhí)行,并把執(zhí)行產(chǎn)生的輸出發(fā)送回瀏覽器顯示出來。

公共網(wǎng)關(guān)接口(CGI),是使得應(yīng)用程序(稱為 CGI 程序或 CGI 腳本)能夠與 Web 服務(wù)器以及客戶端進(jìn)行交互的標(biāo)準(zhǔn)協(xié)議。這些 CGI 程序可以用 Python、PERL、Shell、C 或 C++ 等進(jìn)行編寫。

CGI 架構(gòu)圖

下圖演示了 CGI 的架構(gòu):

CGI 架構(gòu)

Web 服務(wù)器配置

在您進(jìn)行 CGI 編程之前,請(qǐng)確保您的 Web 服務(wù)器支持 CGI,并已配置成可以處理 CGI 程序。所有由 HTTP 服務(wù)器執(zhí)行的 CGI 程序,都必須在預(yù)配置的目錄中。該目錄稱為 CGI 目錄,按照慣例命名為 /var/www/cgi-bin。雖然 CGI 文件是 C++ 可執(zhí)行文件,但是按照慣例它的擴(kuò)展名是 .cgi。

默認(rèn)情況下,Apache Web 服務(wù)器會(huì)配置在 /var/www/cgi-bin 中運(yùn)行 CGI 程序。如果您想指定其他目錄來運(yùn)行 CGI 腳本,您可以在 httpd.conf 文件中修改以下部分:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>
 
<Directory "/var/www/cgi-bin">
Options All
</Directory>

在這里,我們假設(shè)已經(jīng)配置好 Web 服務(wù)器并能成功運(yùn)行,你可以運(yùn)行任意的 CGI 程序,比如 Perl 或 Shell 等。

第一個(gè) CGI 程序

請(qǐng)看下面的 C++ 程序:

#include <iostream>
using namespace std;
 
int main ()
{
    
   cout << "Content-type:text/html\r\n\r\n";    cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Hello World - 第一個(gè) CGI 程序</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<h2>Hello World! 這是我的第一個(gè) CGI 程序</h2>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

編譯上面的代碼,把可執(zhí)行文件命名為 cplusplus.cgi,并把這個(gè)文件保存在 /var/www/cgi-bin 目錄中。在運(yùn)行 CGI 程序之前,請(qǐng)使用 chmod 755 cplusplus.cgi UNIX 命令來修改文件模式,確保文件可執(zhí)行。訪問可執(zhí)行文件,您會(huì)看到下面的輸出:

Hello World! 這是我的第一個(gè) CGI 程序

上面的 C++ 程序是一個(gè)簡單的程序,把它的輸出寫在 STDOUT 文件上,即顯示在屏幕上。在這里,值得注意一點(diǎn),第一行輸出 Content-type:text/html\r\n\r\n。這一行發(fā)送回瀏覽器,并指定要顯示在瀏覽器窗口上的內(nèi)容類型。您必須理解 CGI 的基本概念,這樣才能進(jìn)一步使用 Python 編寫更多復(fù)雜的 CGI 程序。C++ CGI 程序可以與任何其他外部的系統(tǒng)(如 RDBMS)進(jìn)行交互。

HTTP 頭信息

Content-type:text/html\r\n\r\n 是 HTTP 頭信息的組成部分,它被發(fā)送到瀏覽器,以便更好地理解頁面內(nèi)容。HTTP 頭信息的形式如下:

HTTP 字段名稱: 字段內(nèi)容
 
例如
Content-type: text/html\r\n\r\n

還有一些其他的重要的 HTTP 頭信息,這些在您的 CGI 編程中都會(huì)經(jīng)常被用到。

頭信息 描述
Content-type: MIME 字符串,定義返回的文件格式。例如 Content-type:text/html。
Expires: Date 信息變成無效的日期。瀏覽器使用它來判斷一個(gè)頁面何時(shí)需要刷新。一個(gè)有效的日期字符串的格式應(yīng)為 01 Jan 1998 12:00:00 GMT。
Location: URL 這個(gè) URL 是指應(yīng)該返回的 URL,而不是請(qǐng)求的 URL。你可以使用它來重定向一個(gè)請(qǐng)求到任意的文件。
Last-modified: Date 資源的最后修改日期。
Content-length: N 要返回的數(shù)據(jù)的長度,以字節(jié)為單位。瀏覽器使用這個(gè)值來表示一個(gè)文件的預(yù)計(jì)下載時(shí)間。
Set-Cookie: String 通過 string 設(shè)置 cookie。

CGI 環(huán)境變量

所有的 CGI 程序都可以訪問下列的環(huán)境變量。這些變量在編寫 CGI 程序時(shí)扮演了非常重要的角色。

變量名 描述
CONTENT_TYPE 內(nèi)容的數(shù)據(jù)類型。當(dāng)客戶端向服務(wù)器發(fā)送附加內(nèi)容時(shí)使用。例如,文件上傳等功能。
CONTENT_LENGTH 查詢的信息長度。只對(duì) POST 請(qǐng)求可用。
HTTP_COOKIE 以鍵 & 值對(duì)的形式返回設(shè)置的 cookies。
HTTP_USER_AGENT 用戶代理請(qǐng)求標(biāo)頭字段,遞交用戶發(fā)起請(qǐng)求的有關(guān)信息,包含了瀏覽器的名稱、版本和其他平臺(tái)性的附加信息。
PATH_INFO CGI 腳本的路徑。
QUERY_STRING 通過 GET 方法發(fā)送請(qǐng)求時(shí)的 URL 編碼信息,包含 URL 中問號(hào)后面的參數(shù)。
REMOTE_ADDR 發(fā)出請(qǐng)求的遠(yuǎn)程主機(jī)的 IP 地址。這在日志記錄和認(rèn)證時(shí)是非常有用的。
REMOTE_HOST 發(fā)出請(qǐng)求的主機(jī)的完全限定名稱。如果此信息不可用,則可以用 REMOTE_ADDR 來獲取 IP 地址。
REQUEST_METHOD 用于發(fā)出請(qǐng)求的方法。最常見的方法是 GET 和 POST。
SCRIPT_FILENAME CGI 腳本的完整路徑。
SCRIPT_NAME CGI 腳本的名稱。
SERVER_NAME 服務(wù)器的主機(jī)名或 IP 地址。
SERVER_SOFTWARE 服務(wù)器上運(yùn)行的軟件的名稱和版本。

下面的 CGI 程序列出了所有的 CGI 變量。

#include <iostream>
#include <stdlib.h>
using namespace std;

const string ENV[ 24 ] = {                 
        "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",   
        "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",             
        "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",         
        "HTTP_HOST", "HTTP_USER_AGENT", "PATH",            
        "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",      
        "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
        "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",      
        "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",     
        "SERVER_SIGNATURE","SERVER_SOFTWARE" };   

int main ()
{
    
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 環(huán)境變量</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";

   for ( int i = 0; i < 24; i++ )
   {
       cout << "<tr><td>" << ENV[ i ] << "</td><td>";
       // 嘗試檢索環(huán)境變量的值
       char *value = getenv( ENV[ i ].c_str() );  
       if ( value != 0 ){
         cout << value;                                 
       }else{
         cout << "環(huán)境變量不存在。";
       }
       cout << "</td></tr>\n";
   }
   cout << "</table><\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

C++ CGI 庫

在真實(shí)的實(shí)例中,您需要通過 CGI 程序執(zhí)行許多操作。這里有一個(gè)專為 C++ 程序而編寫的 CGI 庫,我們可以從 ftp://ftp.gnu.org/gnu/cgicc/ 上下載這個(gè) CGI 庫,并按照下面的步驟安裝庫:

$tar xzf cgicc-X.X.X.tar.gz 
$cd cgicc-X.X.X/ 
$./configure --prefix=/usr 
$make
$make install

您可以點(diǎn)擊 C++ CGI Lib Documentation,查看相關(guān)的庫文檔。

GET 和 POST 方法

您可能有遇到過這樣的情況,當(dāng)您需要從瀏覽器傳遞一些信息到 Web 服務(wù)器,最后再傳到 CGI 程序。通常瀏覽器會(huì)使用兩種方法把這個(gè)信息傳到 Web 服務(wù)器,分別是 GET 和 POST 方法。

使用 GET 方法傳遞信息

GET 方法發(fā)送已編碼的用戶信息追加到頁面請(qǐng)求中。頁面和已編碼信息通過 ? 字符分隔開,如下所示:

http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2

GET 方法是默認(rèn)的從瀏覽器向 Web 服務(wù)器傳信息的方法,它會(huì)在瀏覽器的地址欄中生成一串很長的字符串。當(dāng)您向服務(wù)器傳密碼或其他一些敏感信息時(shí),不要使用 GET 方法。GET 方法有大小限制,在一個(gè)請(qǐng)求字符串中最多可以傳 1024 個(gè)字符。

當(dāng)使用 GET 方法時(shí),是使用 QUERY_STRING http 頭來傳遞信息,在 CGI 程序中可使用 QUERY_STRING 環(huán)境變量來訪問。

您可以通過在 URL 后跟上簡單連接的鍵值對(duì),也可以通過使用 HTML <FORM> 標(biāo)簽的 GET 方法來傳信息。

簡單的 URL 實(shí)例:Get 方法

下面是一個(gè)簡單的 URL,使用 GET 方法傳遞兩個(gè)值給 hello_get.py 程序。

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

下面的實(shí)例生成 cpp_get.cgi CGI 程序,用于處理 Web 瀏覽器給出的輸入。通過使用 C++ CGI 庫,可以很容易地訪問傳遞的信息:

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>  

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
   
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>使用 GET 和 POST 方法</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("first_name");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "名:" << **fi << endl;  
   }else{
      cout << "No text entered for first name" << endl;  
   }
   cout << "<br/>\n";
   fi = formData.getElement("last_name");  
   if( !fi->isEmpty() &&fi != (*formData).end()) {  
      cout << "姓:" << **fi << endl;  
   }else{
      cout << "No text entered for last name" << endl;  
   }
   cout << "<br/>\n";

   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

現(xiàn)在,編譯上面的程序,如下所示:

$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

生成 cpp_get.cgi,并把它放在 CGI 目錄中,并嘗試使用下面的鏈接進(jìn)行訪問:

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

這會(huì)產(chǎn)生以下結(jié)果:

名:ZARA 
姓:ALI 

簡單的表單實(shí)例:GET 方法

下面是一個(gè)簡單的實(shí)例,使用 HTML 表單和提交按鈕傳遞兩個(gè)值。我們將使用相同的 CGI 腳本 cpp_get.cgi 來處理輸入。

<form action="/cgi-bin/cpp_get.cgi" method="get">
名:<input type="text" name="first_name">  <br />
 
姓:<input type="text" name="last_name" />
<input type="submit" value="提交" />
</form>

下面是上述表單的實(shí)際輸出,請(qǐng)輸入名和姓,然后點(diǎn)擊提交按鈕查看結(jié)果。

使用 POST 方法傳遞信息

一個(gè)更可靠的向 CGI 程序傳遞信息的方法是 POST 方法。這種方法打包信息的方式與 GET 方法相同,不同的是,它不是把信息以文本字符串形式放在 URL 中的 ? 之后進(jìn)行傳遞,而是把它以單獨(dú)的消息形式進(jìn)行傳遞。該消息是以標(biāo)準(zhǔn)輸入的形式傳給 CGI 腳本的。

我們同樣使用 cpp_get.cgi 程序來處理 POST 方法。讓我們以同樣的例子,通過使用 HTML 表單和提交按鈕來傳遞兩個(gè)值,只不過這次我們使用的不是 GET 方法,而是 POST 方法,如下所示:

<form action="/cgi-bin/cpp_get.cgi" method="post">
名:<input type="text" name="first_name"><br />
姓:<input type="text" name="last_name" />
 
<input type="submit" value="提交" />
</form>

向 CGI 程序傳遞復(fù)選框數(shù)據(jù)

當(dāng)需要選擇多個(gè)選項(xiàng)時(shí),我們使用復(fù)選框。

下面的 HTML 代碼實(shí)例是一個(gè)帶有兩個(gè)復(fù)選框的表單:

<form action="/cgi-bin/cpp_checkbox.cgi" 
         method="POST" 
         target="_blank">
<input type="checkbox" name="maths" value="on" /> 數(shù)學(xué)
<input type="checkbox" name="physics" value="on" /> 物理
<input type="submit" value="選擇學(xué)科" />
</form>

下面的 C++ 程序會(huì)生成 cpp_checkbox.cgi 腳本,用于處理 Web 瀏覽器通過復(fù)選框給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
   bool maths_flag, physics_flag;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞復(fù)選框數(shù)據(jù)</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   maths_flag = formData.queryCheckbox("maths");
   if( maths_flag ) {  
      cout << "Maths Flag: ON " << endl;  
   }else{
      cout << "Maths Flag: OFF " << endl;  
   }
   cout << "<br/>\n";

   physics_flag = formData.queryCheckbox("physics");
   if( physics_flag ) {  
      cout << "Physics Flag: ON " << endl;  
   }else{
      cout << "Physics Flag: OFF " << endl;  
   }
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

向 CGI 程序傳遞單選按鈕數(shù)據(jù)

當(dāng)只需要選擇一個(gè)選項(xiàng)時(shí),我們使用單選按鈕。

下面的 HTML 代碼實(shí)例是一個(gè)帶有兩個(gè)單選按鈕的表單:

<form action="/cgi-bin/cpp_radiobutton.cgi" 
         method="post" 
         target="_blank">
<input type="radio" name="subject" value="maths" 
                                    checked="checked"/> 數(shù)學(xué) 
<input type="radio" name="subject" value="physics" /> 物理
<input type="submit" value="選擇學(xué)科" />
</form>

下面的 C++ 程序會(huì)生成 cpp_radiobutton.cgi 腳本,用于處理 Web 瀏覽器通過單選按鈕給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞單選按鈕數(shù)據(jù)</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("subject");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Radio box selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

向 CGI 程序傳遞文本區(qū)域數(shù)據(jù)

當(dāng)需要向 CGI 程序傳遞多行文本時(shí),我們使用 TEXTAREA 元素。

下面的 HTML 代碼實(shí)例是一個(gè)帶有 TEXTAREA 框的表單:

<form action="/cgi-bin/cpp_textarea.cgi" 
         method="post" 
         target="_blank">
<textarea name="textcontent" cols="40" rows="4">
請(qǐng)?jiān)谶@里輸入文本...
</textarea>
<input type="submit" value="提交" />
</form>

下面的 C++ 程序會(huì)生成 cpp_textarea.cgi 腳本,用于處理 Web 瀏覽器通過文本區(qū)域給出的輸入。


#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞文本區(qū)域數(shù)據(jù)</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("textcontent");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Text Content: " << **fi << endl;  
   }else{
      cout << "No text entered" << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

向 CGI 程序傳遞下拉框數(shù)據(jù)

當(dāng)有多個(gè)選項(xiàng)可用,但只能選擇一個(gè)或兩個(gè)選項(xiàng)時(shí),我們使用下拉框。

下面的 HTML 代碼實(shí)例是一個(gè)帶有下拉框的表單:

<form action="/cgi-bin/cpp_dropdown.cgi" 
                       method="post" target="_blank">
<select name="dropdown">
<option value="Maths" selected>數(shù)學(xué)</option>
<option value="Physics">物理</option>
</select>
<input type="submit" value="提交"/>
</form>

下面的 C++ 程序會(huì)生成 cpp_dropdown.cgi 腳本,用于處理 Web 瀏覽器通過下拉框給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞下拉框數(shù)據(jù)</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("dropdown");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Value Selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

在 CGI 中使用 Cookies

HTTP 協(xié)議是一種無狀態(tài)的協(xié)議。但對(duì)于一個(gè)商業(yè)網(wǎng)站,它需要在不同頁面間保持會(huì)話信息。例如,一個(gè)用戶在完成多個(gè)頁面的步驟之后結(jié)束注冊。但是,如何在所有網(wǎng)頁中保持用戶的會(huì)話信息。

在許多情況下,使用 cookies 是記憶和跟蹤有關(guān)用戶喜好、購買、傭金以及其他為追求更好的游客體驗(yàn)或網(wǎng)站統(tǒng)計(jì)所需信息的最有效的方法。

它是如何工作的

服務(wù)器以 cookie 的形式向訪客的瀏覽器發(fā)送一些數(shù)據(jù)。如果瀏覽器接受了 cookie,則 cookie 會(huì)以純文本記錄的形式存儲(chǔ)在訪客的硬盤上?,F(xiàn)在,當(dāng)訪客訪問網(wǎng)站上的另一個(gè)頁面時(shí),會(huì)檢索 cookie。一旦找到 cookie,服務(wù)器就知道存儲(chǔ)了什么。

cookie 是一種純文本的數(shù)據(jù)記錄,帶有 5 個(gè)可變長度的字段:

  • Expires : cookie 的過期日期。如果此字段留空,cookie 會(huì)在訪客退出瀏覽器時(shí)過期。
  • Domain : 網(wǎng)站的域名。
  • Path : 設(shè)置 cookie 的目錄或網(wǎng)頁的路徑。如果您想從任意的目錄或網(wǎng)頁檢索 cookie,此字段可以留空。
  • Secure : 如果此字段包含單詞 "secure",那么 cookie 只能通過安全服務(wù)器進(jìn)行檢索。如果此字段留空,則不存在該限制。
  • Name=Value : cookie 以鍵值對(duì)的形式被設(shè)置和獲取。

設(shè)置 Cookies

向?yàn)g覽器發(fā)送 cookies 是非常簡單的。這些 cookies 會(huì)在 Content-type 字段之前,與 HTTP 頭一起被發(fā)送。假設(shè)您想設(shè)置 UserID 和 Password 為 cookies,設(shè)置 cookies 的步驟如下所示:

#include <iostream>
using namespace std;

int main ()
{
 
   cout << "Set-Cookie:UserID=XYZ;\r\n";
   cout << "Set-Cookie:Password=XYZ123;\r\n";
   cout << "Set-Cookie:Domain=www.hgci.cn;\r\n";
   cout << "Set-Cookie:Path=/perl;\n";
   cout << "Content-type:text/html\r\n\r\n";

   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的 Cookies</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   cout << "設(shè)置 cookies" << endl;  
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

從這個(gè)實(shí)例中,我們了解了如何設(shè)置 cookies。我們使用 Set-Cookie HTTP 頭來設(shè)置 cookies。

在這里,有一些設(shè)置 cookies 的屬性是可選的,比如 Expires、Domain 和 Path。值得注意的是,cookies 是在發(fā)送行 "Content-type:text/html\r\n\r\n 之前被設(shè)置的。

編譯上面的程序,生成 setcookies.cgi,并嘗試使用下面的鏈接設(shè)置 cookies。它會(huì)在您的計(jì)算機(jī)上設(shè)置四個(gè) cookies:

/cgi-bin/setcookies.cgi

獲取 Cookies

檢索所有設(shè)置的 cookies 是非常簡單的。cookies 被存儲(chǔ)在 CGI 環(huán)境變量 HTTP_COOKIE 中,且它們的形式如下:

key1=value1;key2=value2;key3=value3....

下面的實(shí)例演示了如何獲取 cookies。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc cgi;
   const_cookie_iterator cci;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的 Cookies</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";
   
   // 獲取環(huán)境變量
   const CgiEnvironment& env = cgi.getEnvironment();

   for( cci = env.getCookieList().begin();
        cci != env.getCookieList().end(); 
        ++cci )
   {
      cout << "<tr><td>" << cci->getName() << "</td><td>";
      cout << cci->getValue();                                 
      cout << "</td></tr>\n";
   }
   cout << "</table><\n";
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

現(xiàn)在,編譯上面的程序,生成 getcookies.cgi,并嘗試使用下面的鏈接獲取您的計(jì)算機(jī)上所有可用的 cookies:

/cgi-bin/getcookies.cgi

這會(huì)產(chǎn)生一個(gè)列表,顯示了上一節(jié)中設(shè)置的四個(gè) cookies 以及您的計(jì)算機(jī)上所有其他的 cookies:

UserID XYZ 
Password XYZ123 
Domain www.hgci.cn 
Path /perl 

文件上傳實(shí)例

為了上傳一個(gè)文件,HTML 表單必須把 enctype 屬性設(shè)置為 multipart/form-data。帶有文件類型的 input 標(biāo)簽會(huì)創(chuàng)建一個(gè) "Browse" 按鈕。

<html>
<body>
   <form enctype="multipart/form-data" 
            action="/cgi-bin/cpp_uploadfile.cgi" 
            method="post">
   <p>文件:<input type="file" name="userfile" /></p>
   <p><input type="submit" value="上傳" /></p>
   </form>
</body>
</html>

您可以在自己的服務(wù)器上嘗試上面的代碼。


下面是用于處理文件上傳的腳本 cpp_uploadfile.cpp

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc cgi;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的文件上傳</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   // 獲取要被上傳的文件列表
   const_file_iterator file = cgi.getFile("userfile");
   if(file != cgi.getFiles().end()) {
      // 在 cout 中發(fā)送數(shù)據(jù)類型
      cout << HTTPContentHeader(file->getDataType());
      // 在 cout 中寫入內(nèi)容
      file->writeToStream(cout);
   }
   cout << "<文件上傳成功>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

上面的實(shí)例是在 cout 流中寫入內(nèi)容,但您可以打開文件流,并把上傳的文件內(nèi)容保存在目標(biāo)位置的某個(gè)文件中。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)