CGI 的运行原理:
1.客户端访问某个 URL 地址之后,通过 GET/POST/PUT 等方式提交数据,并通过 HTTP 协议向 Web 服务器发出请求。
2.服务器端的 HTTP Daemon(守护进程)启动一个子进程。然后在子进程中,将 HTTP 请求里描述的信息通过标准输入 stdin 和环境变量传递给 URL 指定的 CGI 程序,并启动此应用程序进行处理,处理结果通过标准输出 stdout 返回给 HTTP Daemon 子进程。
再由 HTTP Daemon 子进程通过 HTTP 协议返回给客户端。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h> #define SERV_PORT 9003 char *str_join(char *str1, char *str2); char *html_response(char *res, char *buf); int main(void) {
int lfd, cfd;
struct sockaddr_in serv_addr, clin_addr;
socklen_t clin_len;
char buf[], web_result[];
int len;
FILE *cin; if ((lfd = socket(AF_INET, SOCK_STREAM, )) == -) {
perror("create socket failed");
exit();
} memset(&serv_addr, , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT); if (bind(lfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -) {
perror("bind error");
exit();
} if (listen(lfd, ) == -) {
perror("listen error");
exit();
} signal(SIGCLD, SIG_IGN); while () {
clin_len = sizeof(clin_addr);
if ((cfd = accept(lfd, (struct sockaddr *) &clin_addr, &clin_len)) == -) {
perror("接收错误\n");
continue;
} cin = fdopen(cfd, "r");
setbuf(cin, (char *) );
fgets(buf, , cin); //读取第一行
printf("\n%s", buf); //============================ cgi 环境变量设置演示 ============================ // 例如 "GET /cgi-bin/user?id=1 HTTP/1.1"; char *delim = " ";
char *p;
char *method, *filename, *query_string;
char *query_string_pre = "QUERY_STRING="; method = strtok(buf, delim); // GET
p = strtok(NULL, delim); // /user?id=1
filename = strtok(p, "?"); // /user if (strcmp(filename, "/favicon.ico") == ) {
continue;
} query_string = strtok(NULL, "?"); // id=1
putenv(str_join(query_string_pre, query_string)); //============================ cgi 环境变量设置演示 ============================ int pid = fork(); if (pid > ) {
close(cfd);
}
else if (pid == ) {
close(lfd);
FILE *stream = popen(str_join(".", filename), "r");
fread(buf, sizeof(char), sizeof(buf), stream);
html_response(web_result, buf);
write(cfd, web_result, sizeof(web_result));
pclose(stream);
close(cfd);
exit();
}
else {
perror("fork error");
exit();
}
} close(lfd); return ;
} char *str_join(char *str1, char *str2) {
char *result = malloc(strlen(str1) + strlen(str2) + );
if (result == NULL) exit();
strcpy(result, str1);
strcat(result, str2); return result;
} char *html_response(char *res, char *buf) {
char *html_response_template = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length: %d\r\nServer: mengkang\r\n\r\n%s"; sprintf(res, html_response_template, strlen(buf), buf); return res;
}

user.c

#include <stdio.h>
#include <stdlib.h> // 通过获取的 id 查询用户的信息
int main(void) { //============================ 模拟数据库 ============================
typedef struct {
int id;
char *username;
int age;
} user; user users[] = {
{},
{
,
"taoshihan", }
};
//============================ 模拟数据库 ============================ char *query_string;
int id; query_string = getenv("QUERY_STRING"); if (query_string == NULL) {
printf("没有输入数据");
} else if (sscanf(query_string, "id=%d", &id) != ) {
printf("没有输入id");
} else {
printf("用户信息查询<br>学号: %d<br>姓名: %s<br>年龄: %d", id, users[id].username, users[id].age);
} return ;
}

访问文件流(stream I/O)的方式进行网络数据传输
1.fdopen:打开一个标准的IO流
原型:FILE *fdopen(int fd, const char *type);
fd是用open函数得到文件描述符,type是打开模式

2.setbuf:定义流 stream 应如何缓冲
原型:void setbuf(FILE *stream, char *buffer)

3.fgets:从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内,如果成功,该函数返回相同的 str 参数。
原型:char *fgets(char *str, int n, FILE *stream)

处理并传递参数
4.strtok:分解字符串 str 为一组字符串,delim 为分隔符。
原型:char *strtok(char *str, const char *delim)

5.putenv setenv getenv获取设置环境变量相关函数
头文件:#include4<stdlib.h>
putenv("PATH=/shihan");
char *v=getenv("PATH");
printf("%s\n",v);

拼接字符串
char *str_join(char *str1, char *str2) {
char *result = malloc(strlen(str1) + strlen(str2) + 1);
if (result == NULL) exit(1);
strcpy(result, str1);
strcat(result, str2);

return result;
}
malloc:分配所需的内存空间,并返回一个指向它的指针。
原型:void *malloc(size_t size)

strcpy:把 src 所指向的字符串复制到 dest。
原型:char *strcpy(char *dest, const char *src)

strcat:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
char *strcat(char *dest, const char *src)

[PHP] 通用网关接口CGI 的运行原理的更多相关文章

  1. (一)CGI (通用网关接口) 简介

    CGI (通用网关接口)公共网关接口(Common Gateway Interface,CGI)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能.CGI 应用程序能与浏览器 ...

  2. 【重要】python之模块CGI 通用网关接口

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #CGI模块 import CGI #通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户 ...

  3. CGI(Common Gateway Interface),通用网关接口

    通用网关接口,简称CGI,是一种根据请求信息动态产生回应内容的技术.通过CGI,Web 服务器可以将根据请求不同启动不同的外部程序,并将请求内容转发给该程序,在程序执行结束后,将执行结果作为回应返回给 ...

  4. CGI (通用网关接口)

    CGI cgi即 Common Gateway Interface 译作 通用网关接口 是应用程序与应用程序之间的输入输出协议.比如我们写信,规定了开头一句写称呼,中间写内容,最后署名和日期.看到这种 ...

  5. 通用网关接口 ruby perl web页面 文本处理 脚本语言

    小结: 1.只要可以对标准输入输出进行操作,那么无论任何语言都可以编写CGI程序. <代码的未来> 在Ruby诞生的1993年,互联网还没有现在这样普及,因此Ruby也不是一开始就面向We ...

  6. CGI(通用网关接口)

    公共网关接口 CGI(Common Gateway Interface) 是WWW技术中最重要的技术之一,有着不可替代的重要地位.CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在C ...

  7. CGI 和 FastCGI 协议的运行原理

    目录 介绍 深入CGI协议 CGI的运行原理 CGI协议的缺陷 深入FastCGI协议 FastCGI协议运行原理 为什么是 FastCGI 而非 CGI 协议 CGI 与 FastCGI 架构 再看 ...

  8. 【转】CGI 和 FastCGI 协议的运行原理

    介绍 深入CGI协议 CGI的运行原理 CGI协议的缺陷 深入FastCGI协议 FastCGI协议运行原理 为什么是 FastCGI 而非 CGI 协议 CGI 与 FastCGI 架构 再看 Fa ...

  9. nginx + php-fpm 运行原理

    一.关于nginx 1.1 简单认知 我们都知道nginx 是web服务器. 也知道 用户访问时通过ip和端口访问 nginx. 那么nginx 是如何 通过php 获取数据并返回数据的呢? 1.2 ...

随机推荐

  1. Rabbitmq 消息对列 生产者与消费者的具体实现 springboot

    RabbitMQ 基本介绍 RabbitMQ的设计理念是.只要有接收消息的队列. 邮件就会存放到队列里. 直到订阅人取走. . 如果没有可以接收这个消息的消息队列. 默认是抛弃这个消息的.. 我实现的 ...

  2. 利用wxpy进行微信信息发送详解(一)

    利用wxpy进行微信信息自动发送,简直是骚扰神器,除非拉黑你. 那我们就来设置一个场景吧,五秒发送一次,一次发送10条 首先我们来整理一下思路: ♦1.首先我们要从网上爬去我们想要发送的内容 ♦2.登 ...

  3. python接口自动化2-发送post请求详解(二)

    前言 发送post的请求参考例子很简单,实际遇到的情况却是很复杂的,首先第一个post请求肯定是登录了,但登录是最难处理的.登录问题解决了,后面都简单了. 一.查看官方文档 1.学习一个新的模块,其实 ...

  4. CentOS7打开关闭防火墙与端口

    http://www.javahelp.com.cn/h-nd-747.html#_np=153_1707

  5. C语言数据结构之哈夫曼树及哈夫曼编码的实现

    代码清单如下: #pragma once #include<stdio.h> #include"stdlib.h" #include <string.h> ...

  6. 一种很有意思的数据结构:Bitmap

    昨晚遇到了一种很有意思的数据结构,Bitmap. Bitmap,准确来说是基于位的映射.其中每个元素均为布尔型(0 or 1),初始均为 false(0).位图可以动态地表示由一组无符号整数构成的集合 ...

  7. 基于Allwinner的Audio子系统分析(Android-5.1)

    前言 一直想总结下Audio子系统的博客,但是各种原因(主要还是自己懒>_<),一直拖到现在才开始重新整理,期间看过H8(Android-4.4),T3(Android-4.4),A64( ...

  8. Mac下使用Wine安装Xshell 4和Xftp 4

    下载: (链接: https://pan.baidu.com/s/1o78qisM 密码: 79sq) 安装: 1.安装Wine 参考:http://www.cnblogs.com/EasonJim/ ...

  9. 我也介绍下sizeof与strlen的区别

    本节我也介绍下sizeof与strlen的区别,很简单,就几条: 1. sizeof是C++中的一个关键字,而strlen是C语言中的一个函数:2. sizeof求的是系统分配的内存总量,而strle ...

  10. 从var func=function 和 function func()区别谈Javascript的预解析机制

    var func=function 和 function func()在意义上没有任何不同,但其解释优先级不同:后者会先于同一语句级的其他语句. 即: { var k = xx(); function ...