1.c++ web编程:写出你的CGI程序

2024-05-30 20:38
文章标签 c++ 程序 web 编程 cgi 写出

本文主要是介绍1.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 文件中的部分内容:

 
  1. <Directory "/var/www/cgi-bin">

  2. AllowOverride None

  3. Options ExecCGI

  4. Order allow,deny

  5. Allow from all

  6. </Directory>

  7.  
  8. <Directory "/var/www/cgi-bin">

  9. Options All

  10. </Directory>


五 第一个CGI脚本

以下是一段简短的CGI脚步代码

 
  1. #include <iostream>

  2. using namespace std;

  3.  
  4. int main ()

  5. {

  6.  
  7. cout << "Content-type:text/html\r\n\r\n";

  8. cout << "<html>\n";

  9. cout << "<head>\n";

  10. cout << "<title>Hello World - First CGI Program</title>\n";

  11. cout << "</head>\n";

  12. cout << "<body>\n";

  13. cout << "<h2>Hello World! This is my first CGI program</h2>\n";

  14. cout << "</body>\n";

  15. cout << "</html>\n";

  16.  
  17. return 0;

  18. }

        编译上述代码并且将二进制可执行文件命名为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报文头部都有如下格式:

 
  1. HTTP Field Name: Field Content

  2.  
  3. For Example

  4. Content-type: text/html\r\n\r\n


下表中包含其他一些重要的HTTP报文信息,这些信息在CGI编程中经常会用到。

HeaderDescription
Content-type:A MIME string defining the format of the file being returned. Example is Content-type:text/html
Expires: DateThe 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: URLThe URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file.
Last-modified: DateThe date of last modification of the resource.
Content-length: NThe length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.
Set-Cookie: StringSet the cookie passed through the string

七 CGI环境变量

所有的CGI程序将会使用到下列的CGI环境变量,这些变量在CGI程序中起着重要的作用。

Variable NameDescription
CONTENT_TYPEThe data type of the content. Used when the client is sending attached content to the server. For example file upload etc.
CONTENT_LENGTHThe length of the query information. It's available only for POST requests
HTTP_COOKIEReturn the set cookies in the form of key & value pair.
HTTP_USER_AGENTThe User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.
PATH_INFOThe path for the CGI script.
QUERY_STRINGThe URL-encoded information that is sent with GET method request.
REMOTE_ADDRThe IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
REMOTE_HOSTThe 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_METHODThe method used to make the request. The most common methods are GET and POST.
SCRIPT_FILENAMEThe full path to the CGI script.
SCRIPT_NAMEThe name of the CGI script.
SERVER_NAMEThe server's hostname or IP Address
SERVER_SOFTWAREThe 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设置脚本如下:

      

 
  1. #include <iostream>

  2. using namespace std;

  3.  
  4. int main ()

  5. {

  6.  
  7. cout << "Set-Cookie:UserID=XYZ;\r\n";

  8. cout << "Set-Cookie:Password=XYZ123;\r\n";

  9. cout << "Set-Cookie:Domain=www.tutorialspoint.com;\r\n";

  10. cout << "Set-Cookie:Path=/perl;\n";

  11. cout << "Content-type:text/html\r\n\r\n";

  12.  
  13. cout << "<html>\n";

  14. cout << "<head>\n";

  15. cout << "<title>Cookies in CGI</title>\n";

  16. cout << "</head>\n";

  17. cout << "<body>\n";

  18.  
  19. cout << "Setting cookies" << endl;

  20.  
  21. cout << "<br/>\n";

  22. cout << "</body>\n";

  23. cout << "</html>\n";

  24.  
  25. return 0;

  26. }


        从这个例子中你将了解怎么设置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代码:

 
  1. #include <iostream>

  2. #include <vector>

  3. #include <string>

  4. #include <stdio.h>

  5. #include <stdlib.h>

  6.  
  7. #include <cgicc/CgiDefs.h>

  8. #include <cgicc/Cgicc.h>

  9. #include <cgicc/HTTPHTMLHeader.h>

  10. #include <cgicc/HTMLClasses.h>

  11.  
  12. using namespace std;

  13. using namespace cgicc;

  14.  
  15. int main ()

  16. {

  17. Cgicc cgi;

  18. const_cookie_iterator cci;

  19.  
  20. cout << "Content-type:text/html\r\n\r\n";

  21. cout << "<html>\n";

  22. cout << "<head>\n";

  23. cout << "<title>Cookies in CGI</title>\n";

  24. cout << "</head>\n";

  25. cout << "<body>\n";

  26. cout << "<table border = \"0\" cellspacing = \"2\">";

  27.  
  28. // get environment variables

  29. const CgiEnvironment& env = cgi.getEnvironment();

  30.  
  31. for( cci = env.getCookieList().begin();

  32. cci != env.getCookieList().end();

  33. ++cci )

  34. {

  35. cout << "<tr><td>" << cci->getName() << "</td><td>";

  36. cout << cci->getValue();

  37. cout << "</td></tr>\n";

  38. }

  39. cout << "</table><\n";

  40.  
  41. cout << "<br/>\n";

  42. cout << "</body>\n";

  43. cout << "</html>\n";

  44.  
  45. return 0;

  46. }

点击/cgi-bin/getcookies.cgi看看效果,将会显示出之前设置过的Cookies。

 译自:http://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm (部分略去未译)。

这篇关于1.c++ web编程:写出你的CGI程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016844

相关文章

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee