生活随笔
收集整理的這篇文章主要介紹了
[PHP] 通用网关接口CGI 的运行原理
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
CGI 的運(yùn)行原理:
1.客戶端訪問(wèn)某個(gè) URL 地址之后,通過(guò) GET/POST/PUT 等方式提交數(shù)據(jù),并通過(guò) HTTP 協(xié)議向 Web 服務(wù)器發(fā)出請(qǐng)求。
2.服務(wù)器端的 HTTP Daemon(守護(hù)進(jìn)程)啟動(dòng)一個(gè)子進(jìn)程。然后在子進(jìn)程中,將 HTTP 請(qǐng)求里描述的信息通過(guò)標(biāo)準(zhǔn)輸入 stdin 和環(huán)境變量傳遞給 URL 指定的 CGI 程序,并啟動(dòng)此應(yīng)用程序進(jìn)行處理,處理結(jié)果通過(guò)標(biāo)準(zhǔn)輸出 stdout 返回給 HTTP Daemon 子進(jìn)程。
再由 HTTP Daemon 子進(jìn)程通過(guò) HTTP 協(xié)議返回給客戶端。
#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[
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("接收錯(cuò)誤\n");continue;}cin = fdopen(cfd,
"r");setbuf(cin, (char *)
0);fgets(buf, 1024, cin);
//讀取第一行printf(
"\n%s", buf);//============================ cgi 環(huán)境變量設(shè)置演示 ============================// 例如 "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);
// GETp = strtok(NULL, delim);
// /user?id=1 filename = strtok(p,
"?");
// /userif (strcmp(filename,
"/favicon.ico") ==
0) {continue;}query_string = strtok(NULL,
"?");
// id=1
putenv(str_join(query_string_pre, query_string));//============================ cgi 環(huán)境變量設(shè)置演示 ============================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 <stdio.h>
#include <stdlib.h>
// 通過(guò)獲取的 id 查詢用戶的信息
int main(
void) {//============================ 模擬數(shù)據(jù)庫(kù) ============================typedef
struct {int id;char *
username;int age;} user;user users[] =
{{},{1,"taoshihan",10}};//============================ 模擬數(shù)據(jù)庫(kù) ============================char *
query_string;int id;query_string = getenv(
"QUERY_STRING");if (query_string ==
NULL) {printf("沒(méi)有輸入數(shù)據(jù)");} else if (sscanf(query_string,
"id=%d", &id) !=
1) {printf("沒(méi)有輸入id");} else {printf("用戶信息查詢<br>學(xué)號(hào): %d<br>姓名: %s<br>年齡: %d", id, users[id].username, users[id].age);}return 0;
} ?
?
訪問(wèn)文件流(stream I/O)的方式進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸
1.fdopen:打開(kāi)一個(gè)標(biāo)準(zhǔn)的IO流
原型:FILE *fdopen(int fd, const char *type);
fd是用open函數(shù)得到文件描述符,type是打開(kāi)模式
2.setbuf:定義流 stream 應(yīng)如何緩沖
原型:void setbuf(FILE *stream, char *buffer)
3.fgets:從指定的流 stream 讀取一行,并把它存儲(chǔ)在 str 所指向的字符串內(nèi),如果成功,該函數(shù)返回相同的 str 參數(shù)。
原型:char *fgets(char *str, int n, FILE *stream)
處理并傳遞參數(shù)
4.strtok:分解字符串 str 為一組字符串,delim 為分隔符。
原型:char *strtok(char *str, const char *delim)
5.putenv setenv getenv獲取設(shè)置環(huán)境變量相關(guān)函數(shù)
頭文件:#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:分配所需的內(nèi)存空間,并返回一個(gè)指向它的指針。
原型:void *malloc(size_t size)
strcpy:把 src 所指向的字符串復(fù)制到 dest。
原型:char *strcpy(char *dest, const char *src)
strcat:把 src 所指向的字符串追加到 dest 所指向的字符串的結(jié)尾。
char *strcat(char *dest, const char *src)
轉(zhuǎn)載于:https://www.cnblogs.com/taoshihan/p/8313418.html
總結(jié)
以上是生活随笔為你收集整理的[PHP] 通用网关接口CGI 的运行原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。