cgi程序简单原理叙述

Web客户端和服务器之间的交互用的是一个基于文本的应用级协议,叫做HTTP(hypertext transfer protocol)
web服务器以两种不同的方式向客户端提供内容:
1,取一个磁盘文件,并将它的内容返回给客户端,磁盘文件称为静态内容,而返回文件给客户端的过程称为服务静态内容。
2,运行一个可执行文件,并将它的内容返回给客户端,运行时可执行文件产生的输出称为动态内容,而运行程序返回它的
输出到客户端的过程称为服务动态内容。
关于http响应,下面是一些http状态码
状态代码               状态消息        描述
 200                    成功        处理请求无误    
 301        永久移动        内容已移动到位置头中指明的主机上
 400        错误请求        服务器不能理解请求
 403        禁止        服务器无权访问所请求的文件
 404        未发现        服务器不能找到所请求的文件
 501        未实现        服务器不支持请求的方法
 505        HTTP版本不支持    服务器不支持请求的版本
如果我们思考一下,一个服务器是如何向客户端提供静态内容的,就会发现一个问题,例如,客户端如何将程序参数传递给
服务器,服务器如何将参数传递给它所创建的子进程,子进程的输出发送到哪里?一个称为CGI的实际标准的出现解决了这些
问题(common gateway interface)。
2:服务器如何将参数传递给子进程
在服务器接收到一个如下的请求后:
GET /cgi-bin/adder?1500&213 HTTP/1.1
它调用fork创建一个子进程,并调用execve在子进程的上下文中执行/cgi-bin/adder程序,在调用execve之前,子进程将cgi环境
变量QUERY_STRING设置为"1500&213",adder程序在运行时可以用getenv函数来应用它
3,服务器如何将其他信息传递给子进程
     cgi标准定义了大量的其他环境变量,一个cgi程序在它运行时可以设置这些环境变量
环境变量            描述
QUERY_STRING        程序参数
SERVER_PORT        父进程侦听的端口
REQUEST_METHOD    GET或POST
REMOTE_HOST        客户端的域名
REMOTE_ADDR        客户端的点分十进制IP地址
CONTENT_TYPE        只对POST而言:请求体的MIME类型
CONTENT_LENGTH    只对POST而言:请求体的字节大小
4, 子进程将它的输出发送到哪里
    一个CGI程序将它的动态内容发送到标准输出,在子进程加载并运行CGI程序之前,它使用dup2函数将标准输出重定向到和客户端
相关联的已连接描述符,因此,任何CGI程序写到标准输出的东西会直接到达客户端。
    注意,因为父进程不知道子进程生成的内容的类型和大小,所以子进程就要负责生成content-type和content-length响应报头,以及
终止报头的空行。
    对于post请求,子进程也需要重定向标准输入到已连接描述符,然后,cgi程序会从标准输入中读取请求主题中的参数
    
tiny web服务器
int main(int argc,char* argv[]){
         listenfd = open_listenfd(port);
         while(1){
    connfd = accept(listenfd,....);
    doit(connfd);
    close(connfd)
         }
}
voidn doit(int fd){
    if(static){
          serve_static(fd,filename,filesize);
    }
    if(dynamic){
          serve_dynamic(fd,filename,cgiargs);
    }
}
void server_static(fd,...){
    int srcfd;
    sprintf("buf","HTTP/1.0 200 OK\r\n");
    //...send response header to client
    write(fd,buf,strlen(buf));    

   srcfd = open(filename,O_RDONLY,0);
   p = mmap(0,filesize,PORT_READ,MAP_PRIVATE,srcfd,0);
   write(fd,p,filesize);
   munmap(p,filesize);
}
void serve_dynamic(int fd,char* filename,char* cigargs)
{
    //1:send header    http/1.0 200 ok
    if(fork() == 0){
        setenv("query_string",cgiargs,1);
        dup2(fd,STDOUT_FILENO);
       execve(filename,...);
    }
    wait(NULL);
}
注意:因为cgi程序运行在子进程的上下文中,它能够访问所有在调用execve函数之前就存在的打开文件和环境变量。
因此cgi程序的标准输出上的任何东西都将直接送达到客户端进程,不会受到来自任何父进程的干涉.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值