C++ CGI Web 编程

C++ 也是可以用来写 Web 应用程序的,在众所周知的大厂 腾讯,据说还有很多 Web 应用程序是用 C++ 写的

CGI

CGI ( Common Gateway Interface ),中文公共网关接口,是一套标准,定义了信息是如何在 Web 服务器和客户端脚本之间进行交换

CGI 是一种用于外部网关程序与信息服务器 ( 如 HTTP 服务器 ) 对接的接口标准

  • 目前的版本是 CGI/1.1,CGI/1.2 版本正在推进中。

WEB 浏览

为了更好的理解 CGI 的作用,让我们点击一个超链接,浏览一个特定的网页或 URL,看看会发生什么

  1. 浏览器联系上 HTTP Web 服务器,并请求 URL,即文件名

  2. Web 服务器将解析 URL,并查找文件名

如果找到请求的文件,Web 服务器会把文件发送回浏览器,否则发送一条错误消息, 表明请求了一个错误的文件

  1. Web 浏览器从 Web 服务器获取响应,并根据接收到的响应来显示文件或错误消息

以这种方式搭建起来的 HTTP 服务器,不管何时请求目录中的某个文件,HTTP 服务器发送回来的不是该文件,而是以程序形式执行,并把执行产生的输出发送回浏览器显示出来

CGI 是使得应用程序(称为 CGI 程序或 CGI 脚本)能够与 Web 服务器以及客户端进行交互的标准协议

这些 CGI 程序可以用 Python、PERL、Shell、C 或 C++ 等进行编写

CGI 架构图

Web 服务器配置

百度搜索 CGI 服务器,出现的是千篇一律的 Apache,难不成我们开发一个 CGI demo 还要劳师动众的装一个 Apache

所以这里,我们就不用 Apache 了,而是用 Python 自带的 CGI 容器

如果你是 Windows 系统,如果还没装 Python,那么可以访问 Python 3 安装 安装 Python 3

如果你用的是 Linux 系统,比如 Ubuntu 或者 CentOS 等,或者苹果电脑,那么恭喜你,系统已经自带了 Python

然后创建一个目录用来放 CGI 程序,比如 D:/cgi (Windows) 或者 ~/Downloads/cgi (苹果电脑) 或者 ~/cgi (Linux)

打开一个终端 (命令行提示符,windows) 跳转到上面的目录, 然后执行下面的命令

Python 3.x

python -m http.server --cgi 8080

Python 2.x

python2.7 -m CGIHTTPServer 8080

就可以开启 CGI Server 了

然后在浏览器里输入 http://localhost:8080/ 就会出现下面的页面了

C++ CGI Hello World

在上面提到的 CGI 目录下再创建一个目录 cgi-bin

然后在 cgi-bin 目录下创建文件 index.cpp 然后输入下面的内容

/**
 * file: index.cpp
 * author: 简单教程(www.twle.cn)
 *
 * Copyright © 2015-2065 www.twle.cn. All rights reserved.
 */

#include <iostream>

int main ()
{

   std::cout << "Content-type:text/html;charset=utf-8\r\n\r\n";
   std::cout << "<!DOCTYPE html>";
   std::cout << "<meta charset='utf-8'/>";
   std::cout << "<title>Hello www.twle.cn - 我的 第一个 CGI 程序</title>";
   std::cout << "<h2>Hello www.twle.cn - 我的 第一个 CGI 程序</h2>";

   return 0;
}

然后使用下面的命令编译我们的 hello.cpp

g++ -o index.cgi index.cpp

然后使用 chmod 755 index.cgi 设置权限确保文件可执行

打开浏览器,输入 http://localhost:8080/cgi-bin/index

是不是看到了下面的内容

如果你使用的是 Chrome 那么在网页上点击右键,然后选择 显示网页源代码 可以看到如下内容

<!DOCTYPE html>
<meta charset='utf-8'/>
<title>Hello www.twle.cn - 我的 第一个 CGI 程序</title>
<h2>Hello www.twle.cn - 我的 第一个 CGI 程序</h2>

是不是很熟悉,除了下面这行不知道到哪里去了之外,其它的都还在

std::cout << "Content-type:text/html;charset=utf-8\r\n\r\n";

我们来分析下这个 index.cpp

  1. 主要的代码都是使用 std:cout 将所有的内容输出到标准输出

  2. std::cout << "Content-type:text/html;charset=utf-8\r\n\r\n";

    这行代码是告诉浏览器,我发送的内容类型是 text/html 也就是网页啦,然后发送的内容使用的是 utf-8 编码

    当浏览器收到这行,就会把收到的内容当作网页来显示

    我们把

    Content-type:text/html;charset=utf-8
    

    称之为 HTTP 响应头

    两个回车换行符 \r\n\r\n 是用来分隔响应头和响应内容的

HTTP 头信息

我们刚介绍了 Content-type:text/html;charset=utf-8 是 HTTP 头信息的组成部分

HTTP 头信息的格式如下

HTTP 字段名称: 字段内容

例如

Content-type: text/html;charset=utf-8

如果有多个 HTTP 头部信息,则相互之间使用一个 \r\n 来分别,就像下面这样

Content-type: text/html;charset=utf-8\r\nExpires:01 Jan 1998 12:00:00 GMT

因为 \r\n 就是回车换行符,所以显示出来就会这样子

Content-type: text/html;charset=utf-8
Expires:01 Jan 1998 12:00:00 GMT

下表列出了一些其它的重要的 HTTP 头信息

头信息 描述
Content-type: MIME 字符串,定义返回的文件格式
例如 Content-type:text/html;charset=utf-8
Expires: Date 信息变成无效的日期
浏览器使用它来判断一个页面何时需要刷新
日期字符串的格式应为 01 Jan 1998 12:00:00 GMT
Location: URL 这个 URL 是指应该返回的 URL,而不是请求的 URL
可以使用它来重定向一个请求到任意的文件
Last-modified: Date 资源的最后修改日期
Content-length: N 要返回的数据的长度,以字节为单位
浏览器使用这个值来表示一个文件的预计下载时间
Set-Cookie: string 设置 cookie

CGI 环境变量

所有的 CGI 程序都可以访问下列的环境变量

变量名 描述
CONTENT_TYPE 内容的数据类型。当客户端向服务器发送附加内容时使用。例如,文件上传等功能
CONTENT_LENGTH 查询的信息长度。只对 POST 请求可用
HTTP_COOKIE 以键 & 值对的形式返回设置的 cookies
HTTP_USER_AGENT 用户代理请求标头字段,递交用户发起请求的有关信息,包含了浏览器的名称、版本和其他平台性的附加信息
PATH_INFO CGI 脚本的路径
QUERY_STRING 通过 GET 方法发送请求时的 URL 编码信息,包含 URL 中问号后面的参数
REMOTE_ADDR 发出请求的远程主机的 IP 地址。这在日志记录和认证时是非常有用的
REMOTE_HOST 发出请求的主机的完全限定名称。如果此信息不可用,则可以用 REMOTE_ADDR 来获取 IP 地址。
REQUEST_METHOD 用于发出请求的方法。最常见的方法是 GET 和 POST
SCRIPT_FILENAME CGI 脚本的完整路径
SCRIPT_NAME CGI 脚本的名称
SERVER_NAME 服务器的主机名或 IP 地址
SERVER_SOFTWARE 服务器上运行的软件的名称和版本

我们写一个 CGI 脚本来输出当前的所有 CGI 变量

cgi-bin 目录下新建一个文件 env.cpp 然后输入以下内容

/**
 * file: index.cpp
 * author: 简单教程(www.twle.cn)
 *
 * Copyright © 2015-2065 www.twle.cn. All rights reserved.
 */

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

const std::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 ()
{

   std::cout << "Content-type:text/html;charset=utf-8\r\n\r\n";
   std::cout << "<!DOCTYPE html>";
   std::cout << "<title>CGI 环境变量</title>\n";
   std::cout << "<table border = \"0\" cellspacing = \"1\">";

   for ( int i = 0; i < 24; i++ )
   {
        std::cout << "<tr><td>" << ENV[ i ] << "</td><td>";

        // 尝试检索环境变量的值
        char *value = getenv( ENV[ i ].c_str() );  

        if ( value != 0 ){
            std::cout << value;                                 
        }

        std::cout << "</td></tr>\n";
   }
   std::cout << "</table>\n";

   return 0;
}

然后使用下面的命令编译我们的 env.cpp

g++ -o env.cgi env.cpp

然后使用 chmod 755 env.cgi 设置权限确保文件可执行

打开浏览器,输入 http://localhost:8080/cgi-bin/env.cgi?id=1&name=2

是不是看到了下面的内容

虽然大部分值都是空,但是对 WEB 开发来说最重要的几个都是有值的

C++ 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.