博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[PHP] 通用网关接口CGI 的运行原理
阅读量:6760 次
发布时间:2019-06-26

本文共 4510 字,大约阅读时间需要 15 分钟。

CGI 的运行原理:

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

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#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[1024], web_result[1024]; int len; FILE *cin; if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("create socket failed"); exit(1); } memset(&serv_addr, 0, 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)) == -1) { perror("bind error"); exit(1); } if (listen(lfd, 128) == -1) { perror("listen error"); exit(1); } signal(SIGCLD, SIG_IGN); while (1) { clin_len = sizeof(clin_addr); if ((cfd = accept(lfd, (struct sockaddr *) &clin_addr, &clin_len)) == -1) { perror("接收错误\n"); continue; } cin = fdopen(cfd, "r"); setbuf(cin, (char *) 0); fgets(buf, 1024, 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") == 0) { continue; } query_string = strtok(NULL, "?"); // id=1 putenv(str_join(query_string_pre, query_string)); //============================ cgi 环境变量设置演示 ============================ int pid = fork(); if (pid > 0) { close(cfd); } else if (pid == 0) { 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(0); } else { perror("fork error"); exit(1); } } close(lfd); return 0;} 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;} 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 
#include
// 通过获取的 id 查询用户的信息int main(void) { //============================ 模拟数据库 ============================ typedef struct { int id; char *username; int age; } user; user users[] = { {}, { 1, "taoshihan", 10 } }; //============================ 模拟数据库 ============================ char *query_string; int id; query_string = getenv("QUERY_STRING"); if (query_string == NULL) { printf("没有输入数据"); } else if (sscanf(query_string, "id=%d", &id) != 1) { printf("没有输入id"); } else { printf("用户信息查询
学号: %d
姓名: %s
年龄: %d", id, users[id].username, users[id].age); } return 0;}

 

 

访问文件流(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)

转载地址:http://iwbeo.baihongyu.com/

你可能感兴趣的文章
【SQL 触发器】
查看>>
Kafka server部署配置优化
查看>>
(转) Artificial intelligence, revealed
查看>>
【转】VS项目属性的一些配置项的总结
查看>>
Project、Target、Workspace and Scheme
查看>>
topas top vmstat
查看>>
Linux基本权限学习
查看>>
掌握jQuery插件开发
查看>>
git基本用法
查看>>
Spring Session - 使用Redis存储HttpSession例子
查看>>
如何利用框选工具获取多边形范围?
查看>>
Java读取Excel数据
查看>>
input输入框回车事件响应
查看>>
[转]win7 如何升级PowerShell
查看>>
mongodb基本操作
查看>>
工具使用——印象(汇总)
查看>>
020 RDD的理解
查看>>
Flask 2 程序的基本结构1
查看>>
sass的学习笔记
查看>>
uploadify上传带参数及接收参数的方法
查看>>