C++ web程式設計:寫出你的CGI程式
一 什麼是CGI
CGI(The Common Gateway Interface):通用閘道器介面,定義web伺服器和客戶指令碼進行資訊互動的一系列標準。
二 web瀏覽器
為了瞭解CGI的概念,讓我們來看看當我們單擊一個超連結來瀏覽一個特定的web頁或URL的時候,背後會發生什麼事?
(1)瀏覽器首先會連結HTTP web 伺服器並且請求一個URL 頁面;
(2) WEB伺服器將會解析這個URL並且查詢請求的檔名,如果找到了請求檔案伺服器就會將這個檔案傳送回瀏覽器,否則傳送回一個包含錯誤資訊提示的頁面指示你請求的是一個伺服器並不包含的檔案。
(3)WEB瀏覽器將接受來自伺服器端的響應,並且向發出請求的使用者顯示接收到的檔案。
然而,HTTP伺服器也可能會以如何這種方式進行配置,那就是無論什麼時候接受到對特定目錄下的檔案的請求,伺服器不會將這個檔案傳送回客戶端,而是它作為一個程式被伺服器執行,併產生出輸出傳送回客戶端瀏覽器進行顯示。
CGI(The Common Gateway Interface)是一個標準化的協議,能夠使應用程式(通常稱為CGI程式或CGI指令碼)同web伺服器和客戶端進行互動。CGI程式能夠用Python, PERL, Shell, C or C++等語言來實現。
三 CGI程式結構圖
下圖簡單的展示了CGI程式架構
四 web伺服器配置
在你著手寫CGI程式之前,確保你的web伺服器支援CGI程式並且配置成處理CGI程式。所有的能夠被HTTP伺服器執行的CGI程式都被存放在預先配置好的目錄下面,這個目錄叫做CGI目錄,並且按照約定命名為 /var/www/cgi-bin,並且約定CGI檔案的字尾名為.cgi ,儘管它們是c++可執行檔案。
一般的,Apache 伺服器在/var/www/cgi-bin目錄下配置檔案來執行CGI程式,如果你想要宣告另外的目錄來執行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>
五 第一個CGI指令碼
以下是一段簡短的CGI腳步程式碼
#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 - First CGI Program</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<h2>Hello World! This is my first CGI program</h2>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
編譯上述程式碼並且將二進位制可執行檔案命名為cplusplus.cgi,儲存路徑為/var/www/cgi-bin目錄下,執行chmod 755 cplusplus.cgi 命令使得該檔案為可執行的。現在,如果你點選cplusplus.cgi然後就會產生如下輸出:
Hello World! This is my first CGI program
上面的C++程式是一個將輸出寫入標準輸出檔案(stdout)的簡單程式。這段程式碼中有一個很重要的一點那就是第一行程式碼:Content-type:text/html\r\n\r\n,這行被髮送回瀏覽器,指明瀏覽器顯示的文字型別。現在你應該瞭解了CGI的基本概念了,你也可以使用python寫出更多複雜的CGI程式,C++ CGI程式能與其他任何外部系統進行資訊互動,例如像RDBMS。
六 HTTP報文頭部
這行字串” Content-type:text/html\r\n\r\n”是傳送回瀏覽器的HTTP報文頭部的一部分,所有的HTTP報文頭部都有如下格式:
HTTP Field Name: Field Content
For Example
Content-type: text/html\r\n\r\n
下表中包含其他一些重要的HTTP報文資訊,這些資訊在CGI程式設計中經常會用到。
Header | Description |
---|---|
Content-type: | A MIME string defining the format of the file being returned. Example is Content-type:text/html |
Expires: Date | The date the information becomes invalid. This should be used by the browser to decide when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT. |
Location: URL | The URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file. |
Last-modified: Date | The date of last modification of the resource. |
Content-length: N | The length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file. |
Set-Cookie: String | Set the cookie passed through the string |
七 CGI環境變數
所有的CGI程式將會使用到下列的CGI環境變數,這些變數在CGI程式中起著重要的作用。
Variable Name | Description |
---|---|
CONTENT_TYPE | The data type of the content. Used when the client is sending attached content to the server. For example file upload etc. |
CONTENT_LENGTH | The length of the query information. It's available only for POST requests |
HTTP_COOKIE | Return the set cookies in the form of key & value pair. |
HTTP_USER_AGENT | The User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser. |
PATH_INFO | The path for the CGI script. |
QUERY_STRING | The URL-encoded information that is sent with GET method request. |
REMOTE_ADDR | The IP address of the remote host making the request. This can be useful for logging or for authentication purpose. |
REMOTE_HOST | The fully qualified name of the host making the request. If this information is not available then REMOTE_ADDR can be used to get IR address. |
REQUEST_METHOD | The method used to make the request. The most common methods are GET and POST. |
SCRIPT_FILENAME | The full path to the CGI script. |
SCRIPT_NAME | The name of the CGI script. |
SERVER_NAME | The server's hostname or IP Address |
SERVER_SOFTWARE | The name and version of the software the server is running. |
下面這段程式碼列出了所有的CGI變數,點選Get Environment可看結果。
#include <iostream>
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 Envrionment Variables</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>";
// attempt to retrieve value of environment variable
char *value = getenv( ENV[ i ].c_str() );
if ( value != 0 ){
cout << value;
}else{
cout << "Environment variable does not exist.";
}
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
八 C++CGI庫
在該FTP伺服器上ftp://ftp.gnu.org/gnu/cgicc/ 提供了C++ CGI庫以供下載,我們從上面下載CGI 庫並一下步驟進行安裝:
$tar xzf cgicc-X.X.X.tar.gz
$cd cgicc-X.X.X/
$./configure --prefix=/usr
$make
$make install
並且你可以閱讀相關文件。C++ CGI Lib Documentation 。
九 GET 與POST方法
當你需要從瀏覽器客戶端傳遞資訊至web伺服器端並最終送至CGI程式的時候,你將必然會遇到很多的問題。大部分的瀏覽器使用兩種方法傳送資訊至瀏覽器:GET方法和POST方法,進行過WEB開發的人應該對其很熟悉。
1. 使用GET方法傳送資訊
GET方法將編碼過的使用者資訊附加在頁面請求上傳送,頁面請求和這些編碼資訊使用?進行分割,如下所示:
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
GET方法是瀏覽器傳送資訊之伺服器端所採用的預設的方法,採用這種方法傳送時,在你的瀏覽器位址列上在URL後面會附加上一串字串,如果你傳輸密碼或其他敏感資訊至伺服器端的時候不要使用GET方法,GET方法有長度限制,在一個請求字串中,最多隻能傳送1024的字元。
當使用GET方法的時候,HTTP報文頭採用QUERY_STRING傳送資訊,並且將通過QUERY_STRING環境變數進入你的CGI程式。
您能夠使用簡單的鍵-值組合附加在URL後傳遞資訊,或者你也可使用HTML中的<FORM>標籤通過使用GET方法來傳遞資訊。
2. 使用POST方法傳送資訊
CGI程式中較為通用的且更為可靠地傳遞資訊的方法是POST方法,POST傳遞的報文資訊和GET方法沒什麼兩樣,但是跟GET方法的將字串資訊附加於URL之後並且用?分隔有所區別的是,POST方法使用分離的報文段分別傳送URL和要傳輸的資訊。這些資訊會被CGI指令碼以標準輸入的形式接收。
(注:在原文中作者給出了HTML各種控制元件傳遞資訊給CGI指令碼的例子,有興趣的朋友可以去看看)
十 在CGI中使用Cookies
伺服器可能會以Cookies的形式傳送資料給客戶端瀏覽器上,瀏覽器也許會接收這些Cookies,並且會以簡單文字的形式儲存在使用者的硬碟上,當使用者訪問該web站點的另外頁面的時候,這些Cookies就會有用處了,伺服器就會據此知道使用者記錄了那些資訊。
Cookies資訊格式包含如下5個變數:
(1) Expires:包含Cookies的過期資訊。如果變數值為空,當客戶端關閉瀏覽器時,Cookies就會過期。
(2) Domain:web站點的域名資訊。
(3) Path:設定Cookies的web頁或目錄的路徑。如果想要從任何頁面或目錄獲取Cookies資訊,此變數設為空值。
(4) Secure:如果該欄位設定為"secure",那麼Cookies將只能被安全伺服器獲取,如果該欄位為空,則沒有該限制。
(5) Name=Value:Cookies以鍵-值對的形式設定或獲取。
1. 設定Cookies
傳送Cookies資訊至瀏覽器是非常容易的,這些Cookies將會附加在在HTTP報文頭的Content-type域前。假設你想要以Cookies的方式設定UserID和Password,那麼簡單的CGI設定指令碼如下:
#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.tutorialspoint.com;\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>Cookies in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "Setting cookies" << endl;
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
從這個例子中你將瞭解怎麼設定Cookies,那就是使用Set-Cookie來設定Cookies。
設定Cookies屬性的時候,Expires, Domain, and Path是可選的,值得注意的一點是Cookies的設定是在傳送"Content-type:text/html\r\n\r\n”之前。執行/cgi-bin/setcookies.cgi將會在你的電腦上設定Cookies。
2.獲取Cookies
獲取Cookies也非常簡單,Cookies都儲存在CGI的環境變數HTTP_COOKIE中,並且具有如下的格式:
key1=value1;key2=value2;key3=value3....
以下就是一段獲取Cookies的簡短的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 cgi;
const_cookie_iterator cci;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Cookies in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
// get environment variables
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;
}
點選/cgi-bin/getcookies.cgi看看效果,將會顯示出之前設定過的Cookies。
譯自:http://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm (部分略去未譯)。
相關文章
- 好程式設計師寫出來的程式碼,就叫好程式碼嗎?你錯了!程式設計師
- Go Web 程式設計入門--編寫 Web 中介軟體GoWeb程式設計
- 老程式設計師的10個程式設計小技巧,教你寫出高質量程式碼!程式設計師
- 這些資深程式設計師的程式設計小技巧,教你寫出高質量程式碼!程式設計師
- WEB程式設計開發常用的程式碼Web程式設計
- C++核心程式設計C++程式設計
- c++ 程式通用多執行緒單例設計 c++ web 框架設計經驗談C++執行緒單例Web框架
- 程式設計師,你真的會寫簡歷嗎?程式設計師
- 一個老程式設計師的程式設計之路,寫給年輕的程式設計師們程式設計師
- C++程式設計實現C++程式設計
- C++ 提高程式設計C++程式設計
- C++提高程式設計C++程式設計
- 好程式設計師web前端教程分享JavaScript簡寫方法程式設計師Web前端JavaScript
- 《程式設計珠璣》程式碼之路12:如何用C/C++實現array[-1]並利用它寫出優美的程式碼程式設計C++
- 程式設計師程式設計,你的練習是不是有效的?程式設計師
- 【1024程式設計師節】程式設計師,你學程式設計的初衷是什麼?程式設計師
- 程式設計師寫的跳轉程式設計師
- 程式設計師如何寫出好程式碼?程式設計師
- 好程式設計師不寫程式碼程式設計師
- Windows 程式設計簡介從C/C++到Windows程式設計Windows程式設計C++
- Web伺服器程式設計Web伺服器程式設計
- 好程式設計師web前端分享css常用屬性縮寫程式設計師Web前端CSS
- C++的函數語言程式設計C++函數程式設計
- 菜雞程式設計師是如何寫程式碼的?程式設計師
- 程式設計師的工作就只有寫程式碼麼???程式設計師
- 物件導向程式設計C++物件程式設計C++
- C++高階程式設計pdfC++程式設計
- C++ & Intel MKL 混合程式設計C++Intel程式設計
- C++核心程式設計筆記C++程式設計筆記
- c++簡單程式設計-3C++程式設計
- C++提高程式設計-模板C++程式設計
- C++提高程式設計-STLC++程式設計
- QML之C++混合程式設計C++程式設計
- 羨慕程式設計師的高薪?你會讓你的孩子當程式設計師嗎?程式設計師高薪
- 給程式設計師的幾點程式設計經驗----《編寫高質量程式碼》程式設計師
- 中國程式設計師與美國程式設計師寫程式碼的區別分析程式設計師
- 你說寫程式碼,最常用的3個設計模式是啥?設計模式
- 當程式設計師寫不出程式碼了……程式設計師
- Linux C/C++程式設計中的多執行緒程式設計基本概念LinuxC++程式設計執行緒