目录
CGI的引入及原理
我们在之前的篇目中讲到了,在我们客户端向服务器发送请求的时候,如果发送的内容是一个目录或者一个普通文件,我们给他们返回的是一个静态的网页。而接下来我们就讲解另一种情况,如果请求资源路径下面是一个可执行文件,那么这个时候就要我们使用(CGI)机制。
那么什么是CGI机制呢,我们在http的角度来看,实际上HTTP对于可执行文件是不会直接处理的,他会把客户端传来的参数传递给其可执行程序,可执行程序进行程序的执行,当结束的时候,再把处理的结果返回给我们的HTTP,HTTP拿到处理结果再返回给我们的客户端,这套机制就是CGI机制。
但是这个时候又有一个问题了,就是说我们CGI这个机制是一个程序,当被加载到内存的时候是一个进程,我们怎么通过进程来去执行另一部分的程序呢?——这就用到了程序替换,但是直接替换的话,我们之前的代码就都被覆盖了,我们肯定不能直接替换,那么应该怎么做呢,我们可以来创建子进程帮助我们完成程序替换,然后再把结果返回给我们。
这个时候问题又来了,我们需要执行的资源在哪里?简而言之,经过了前面的分析之后,请求资源可执行程序其实就是我们的路径。
对于GET方法而言:就是路径path+query_string。
对于POST的方法而言:就是路径path+body(传参)。
在我们之前的博客中已经将需要启用cgi的处理的请求标注了出来,所以在这里我们来测试以下我们的代码,当需要执行普通文件和可执行性程序的时候,会把他们进行分别处理。
int ProcessCgi()
{
std::cout<<"debug"<<"Use CGI Model"<<std::endl;
}
我们在这里用本地环回进行测试,我们输入请求行,请求的是普通文件,然后回车。
我们可以看到的是给我们返回的就是一个普通文件的内容,而接下来我在页面上创建一个可执行文件,并给它赋上可执行权限,然后进行请求。
然后我们在对对这个可执行程序发起请求。
我们看到CGI测试的代码,说明现在已经执行到了CGI程序。
子进程创建与程序替换
我们刚才讲到,因为执行cgi程序需要进行程序替换,而如果直接进行程序替换,那么剩下的代码和程序就找不到了,所以我们可以创建子进程,让它帮我们完成程序替换。
pid_t pid = fork();
if(pid == 0 )
{ //child
}
else if(pid < 0)
{ //error
}
else{ //parent
}
我们创建完了子进程,让其帮助我们处理cgi机制,并返回给结果给我们的父进程, 而想要让程序去执行另一部分的代码,需要进行程序替换,程序替换有六个程序替换函数,我们应该选择哪个来进行程序替换呢?
所以我这里选择的是execl这个替换函数。
在这里说明以下参数的问题:
path:表示执行目标文件的路径
arg:表示你想怎么样来执行这个文件,这里可以直接把文件名(可带路径直接传给他)
最终以nullptr作为结尾。