[译]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;
}

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可看结果。

 1 #include <iostream>
 2 using namespace std;
 3
 4 const string ENV[ 24 ] = {
 5         "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
 6         "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",
 7         "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",
 8         "HTTP_HOST", "HTTP_USER_AGENT", "PATH",
 9         "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
10         "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
11         "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",
12         "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",
13         "SERVER_SIGNATURE","SERVER_SOFTWARE" };
14
15 int main ()
16 {
17
18    cout << "Content-type:text/html\r\n\r\n";
19    cout << "<html>\n";
20    cout << "<head>\n";
21    cout << "<title>CGI Envrionment Variables</title>\n";
22    cout << "</head>\n";
23    cout << "<body>\n";
24    cout << "<table border = \"0\" cellspacing = \"2\">";
25
26    for ( int i = 0; i < 24; i++ )
27    {
28        cout << "<tr><td>" << ENV[ i ] << "</td><td>";
29        // attempt to retrieve value of environment variable
30        char *value = getenv( ENV[ i ].c_str() );
31        if ( value != 0 ){
32          cout << value;
33        }else{
34          cout << "Environment variable does not exist.";
35        }
36        cout << "</td></tr>\n";
37    }
38    cout << "</table><\n";
39    cout << "</body>\n";
40    cout << "</html>\n";
41
42    return 0;
43 }
44  

八、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 (部分略去未译)。

时间: 2024-09-30 16:06:38

[译]C++ WEB编程:写出你的CGI程序的相关文章

小程序初体验:手把手教你写出第一个小程序(一)

本文笔者将根据quick start中的范例代码,带大家简单地剖析一下小程序的运行方式,并介绍小程序开发中一些通用的特性,带着大家一步步写出自己的小程序. 适用对象:前端初学者,对小程序开发感兴趣者 tips:由于笔者也是一位前端菜鸟,所以尽量用简单直白的语言为大家讲解,如有说的不到位的地方,还望多多指教. 吊了我们一年胃口的小程序终于和大家见面了.经过了一天的发酵,小程序已经成为了今天的超级头条(汪汪哭晕在厕所). 经历了一天媒体对小程序的狂轰滥炸,相信大家对于小程序一定充满了好奇.与其跟风转

如何写出高性能的.net程序

本文是一个小工作总结. 总结这么久的性能优化经验. 有一次电话面试, 面试官说我简历里提到了性能优化, 他问我性能优化有什么章法吗?给他说说. 我当时真迷糊了. 真的,做了这么久的性能优化还真不知道性能优化有什么章法. 一直是自己凭感觉乱弄, 运气比较好, 还真的可以弄到点子上, 运行时间急剧缩短. 一提起优化, 大家第一反应就是算法. 不过说来惭愧, 我这种懒人, 对算法最一头雾水了, 算法导论买回来看了前几页就扔那压东西了, 现在好像还丢了. 不知道哪次搬家弄没了. 所以本文的主要核心就是如

用C#写出一个控制台五子棋程序。学习C#中遇到的比较有意思的程序。

首先,在Main方法中定义棋盘的行数列数,int hang,lie = 15:然后定义数组,string[ , ] qipan = new string[hangshu,lieshu]; 然后写一个下棋的方法  (其中用*代表白棋,#代表黑棋) static void Xiaqi (string[,] qipan,int hang,int lie,bool baizixia) { qipan[hang, lie] = baizixia ? "*":"#"; } ?

只用这 6 个字符,就可以写出任意 JavaScript 代码!

你可能在网上见过有人用 几个不同的字符写的各种稀奇古怪的 JavaScript 代码,虽然看起来奇怪,但是能正常运行!比如这个: (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]] 复制代码 你猜运行结果是什么?你可以自己去控制台试一下. 看起来很神奇,但这到底是怎么回事呢? 事实上,你几乎可以用下面这 6 个字符写出任意的 JavaScript 程序: []()!+ 复制代码 很多人都知道这个技巧,但是没

用js写已知abc+cba = 1333,其中a、b、c均为一位数,编程求出满足条件的a、b、c所有组合。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Consolas; color: #888471 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Consolas; color: #888471; min-height: 33.0px } span.Apple-tab-span { white-space: pre } <!--<script type="text/

[译] 如何在React中写出更优秀的代码

目录 我们先来看 Linting 利用组件模块性.复用性和组合性 propTypes 和 defaultProps 知道何时创建新组件 组件 vs 纯组件 vs 无状态函数组件 无状态函数组件 纯组件 使用 React 开发工具 使用内联条件语句 尽可能使用代码片段库 React 本质 - 学习 React 是如何工作的 快速回顾 在React中写出更好代码的9条建议:学习关于 Linting, propTypes, PureComponent 等. Rajat S · 2018 年 4 月 1

10个编程小技巧,教你写出高质量代码!

你会写代码吗你会写高质量代码吗你知道怎么写高质量代码吗不要一上来就开始写代码想清楚,再动手今天,分享10个写代码的小技巧教你写出高质量代码↓↓↓ 1.重构思维模式 不要一上来就开始写代码,要掌握尽量多的重构方法,重构思维方式,掌握重构并不一定是要对原来代码的重构,而是让自己在操作之前就想好该怎么去进行. 2.搞清需求再动手 看到需求之后,肯定多多少少会有一些问题,或是理解上的错误,或是功能实现上的问题,这时,必须要交流清楚,否则,后续将会有更多问题. 3.文档也要写 可能不少人觉得文档没人看,写

python web编程-CGI帮助web服务器处理客户端编程

这几篇博客均来自python核心编程 如果你有任何疑问,欢迎联系我或者仔细查看这本书的地20章 另外推荐下这本书,希望对学习python的同学有所帮助 概念预热 eb客户端通过url请求web服务器里的静态页面,但是要怎么做到洞察不同用户同的输入?比如说表单提交等来产生不同的返回结果呢 一个简单的思路是web服务器把这些请求提交给另外一个程序,它接受用户输入然后处理,根据输入生成一个静态的html文件交给web服务器 复杂上面这样的流程程序就是CGI,是单独出来的 创建HTML 的CGI 应用程

如何写出更好的Java代码

Java是最流行的编程语言之一,但似乎并没有人喜欢使用它.好吧,实际上Java是一门还不错的编程语言,由于最近Java 8发布了,我决定来编辑一个如何能更好地使用Java的列表,这里面包括一些库,实践技巧以及工具. 这篇文章在GitHub上也有.你可以随时在上面贡献或者添加你自己的Java使用技巧或者最佳实践. 编码风格 结构体 builder模式 依赖注入 避免null值 不可变 避免过多的工具类 格式 文档 Stream 部署 框架 Maven 依赖收敛 持续集成 Maven仓储 配置管理