0
点赞
收藏
分享

微信扫一扫

CGI通用网关接口


Common Gatway Interface

原理

简介

CGI 是 Web服务器和程序动态生成数据之间的通用接口

CGI通用网关接口_C语言

服务器和CGI程序之间是通过标准输入输出来进行数据传递的,需要环境变量的协作才可以实现

基本流程:

  1. 通过浏览器将用户请求送到服务器
  2. 服务器接收用户请求并交给CGI程序处理
  3. CGI程序把处理结果传送给服务器
  4. 服务器把结果送回到浏览器

对于Windows系统而言,还可以通过profile文件进行数据传输(如ini文件)

每个CGI程序只能处理一个用户请求,在激活一个CGI程序进程时也创建了属于该进程的环境变量。

环境变量

对于CGI程序来说,它继承了系统的环境变量, CGI环境变量在CGI程序启动时初始化,在结束时销毁。

当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了关于HTTP服务器、客户端、CGI传输过程等相关内容。

与请求相关的环境变量

名称

说明

REQUEST_METHOD

服务器与CGI程序之间的信息传输方式

QUERY_STRING

采用GET时所传输的信息

CONTENT_LENGTH

STDIO中有效信息长度

CONTENT_TYPE

指示所传来的信息的MIME类型

CONTENT_FILE

使用Windows HTTPd/WinCGI标准时,用来传送数据的文件名

PATH_INFO

路径信息

PATH_TRANSLATED

CGI程序的完整路径名

SCRIPT_NAME

所调用的CGI程序的名字

与服务器相关的环境变量

名称

说明

GATEWAY_INTERFACE

服务器所实现的CGI版本

SERVER_NAME

服务器的IP或名字

SERVER_PORT

主机的端口号

SERVER_SOFTWARE

调用的CGI程序名称和版本号

与客户端相关的环境变量

名称

说明

REMOTE_ADDR

客户机的IP地址

REMOTE_HOST

客户机的主机名

ACCEPT

能接收的应答方式

ACCEPT_ENCODING

支持的编码方式

ACCEPT_LANGUAGE

可接受的语言

AUTORIZATION

认证方式

FORM

客户机地址

IF_MODIFIED_SINGCE

当用get方式请求并且只有当文档比指定的日期更早时才返回数据

PRAGMA

设定将来要用到的服务器代理

REFFERER

链接到当前文档的文档的URL

USER_AGENT

客户端浏览器的信息

  • CGI传送给Web服务器的信息可以用各种格式,通常是以HTML文本或者XML文本的形式

1. 传输HTML,文本第一行输出的内容必须是"content-type:text/html\n\n"
2. 传输XML,文本第一行输出的内容必须是"content-type:text/xml\n\n"
3. 其他的一些格式:JIF(image/gif)、JPEG(image/jpeg)、AVI(video/avi)

两个重要环境变量

  • ​QUERY_STRING​​:在浏览器端以GET的方法输入的数据,数据的内容就是url问号后的内容

char *data = getenv("QUERY_STRING");

  • ​CONTENT_LENGTH​​:在浏览器端以POST方法输入的数据的字节数,数据的内容通过标准输入获取

//1. 数据的长度
char *len = getenv("CONTENT_LENGTH");
//2、根据长度 从标准输入设备 获取内容
char data[128]="";
fgets(data, atoi(len)+1, stdin);

POST方法

客户端来的用户数据将存放在CGI进程的标准输入中,同时将用户数据的长度赋予环境变量中的CONTENT_LENGTH

GET方法

客户端来的用户数据存放到到环境变量QUERY_STRING

CGI程序的执行流程:

  • 查询与该CGI程序进程相应的环境变量:
    REQUEST_METHOD,如果是POST,就从环境变量中获取数据的长度len,然后到该进程相应的标准输入取出len长的数据。
    如果是GET,则用户数据就在环境变量的QUERY_STRING中

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

int get_inputs(){
int length;
char *method;
char *inputstring;
method = getenv("REQUEST_METHOD"); //将返回结果赋予指针
if(method == NULL) return 1; //找不到环境变量REQUEST_METHOD
if(!strcmp(method, "POST")) { // POST方法
length = atoi(getenv("CONTENT_LENGTH")); //结果是字符,需要转换
if(length != 0) {
inputstring = malloc(sizeof(char)*length + 1) //必须申请缓存,因为stdin是不带缓存的。
fread(inputstring, sizeof(char), length, stdin); //从标准输入读取一定数据
}
}else if(!strcmp(method, "GET")){
Inputstring = getenv("QUERY_STRING");
length = strlen(inputstring);
}
}

先判断“REQUEST_METHOD”是否存在,程序会更健壮,否则在某些情况下可能会造成程序崩溃。

假若CGI程序不是由服务器调用的,环境变量集里就没有与CGI相关的环境变量(如REQUEST_METHOD,REMOTE_ADDR等)添加进来

CGI数据输出

在CGI程序中的标准输出stdout是经过重定义了的,没有在服务器上产生任何的输出内容,而是被重定向到客户浏览器

可以用打印来实现客户端新的HTML页面的生成。

CGI标题

CGI的格式输出内容必须组织成标题/内容的形式,CGI标准规定了CGI程序可以使用的三个HTTP标题。

标题必须占据第一行输出,而且必须随后带有一个空行

标题

描述

Content-Type

设定随后输出数据的MIME类型

Location

设定输出为另外一个文档

Status

指定HTTP状态码

Content-Type

向标准输出发送网页内容要遵循MIME格式

任意输出前面必须要有一个用于定义MIME类型的输出内容,随后必须跟一个空行。

printf("Content-Type:text/html\n\n");
printf("Welcome\n");

MIME类型以类型/子类型(type/subtype)的形式表示。

  • 其中type表示一下几种典型文件格式的一种:

text、audio、video、image、application、mutipart、message

  • Subtype则用来描述具体所用的数据格式。

类型

说明

Application/msword

word文档

Application/octet-stream

一种通用二进制文件格式

Application/zip

zip压缩文件

Application/pdf

pdf文件

Location

使用location ,一个CGI可以使用当前用户转而访问同一服务器上的另外一个程序,甚至可以访问一个url

使用Location的格式为:Location:Filename/URL

printf("Location:/test.html\n\n");
//这与直接链接到test.html的效果是一样的。

printf("Location:http:*//www.baidu.com/\n\n");
//由于该URL并不指向当前服务器,用户浏览器并不会直接链接到指定的URL,而是给用户输出提示信息。

Demo

GET方式:计算a + b的值

url: ​​http://ip:port/add?a=nn&b=nn​​

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

int main(){
char * method = NULL;
char *query_string = NULL;
printf("Content-Type:text/html\r\n\r\n");

method = getenv("REQUEST_METHOD");
if(method == NULL){
printf("<html> <p> UNKNOWN METHOD</p></html>");
return;
}
if(strcasecmp(method,"POST") == 0){
printf("<html> <p> UNSUPPORTED METHOD</p></html>");
return 0;
}
query_string = getenv("QUERY_STRING");
if(query_string == NULL){
printf("<html> <p> PARAMETER ERROR </p></html>");
return 0;
}
int a = 0;
int b = 0;
int i = 0;
char * start = query_string+2;
char * end = NULL;
// format: a=xxx&b=xxx
for(i = 0;i<strlen(query_string);i++){
if(*(query_string+i) == '&'){
end = query_string+i;
break;
}
}
*end = '\0';
a = atoi(start);
start = end +3;
b = atoi(start);
printf("<html> <p> %d + %d = %d </p></html>",a,b,a+b);
return 0;
}

显示效果如下:

CGI通用网关接口_环境变量_02

参考

  1. ​​t.csdn.cn/44wV4​​
  2. ​​t.csdn.cn/tkgPJ​​
  3. ​​t.csdn.cn/JqlKj​​
  4. ​​t.csdn.cn/afcOz​​
举报

相关推荐

0 条评论