本项目是建立在TCP协议的基础上,实现HTTP层的功能,可以根据客户端的请求返回相应的资源,也可以调用客户端申请的可执行程序对其传递的参数进行处理。
1,对TCP层功能的调用和使用:
本项目主要借助TCP层的功能来建立链接,链接建立好之后,该全链接会被放入全链接队列中,什么时候HTTP层有需求,随时来拿即可。TCP层的功能也就到此为止了。
2,请求报文和响应报文:
对于请求报文,需要按照请求报文的格式(请求报头、请求行、空行、请求正文)进行读取。由于请求报文不一定有请求正文,所以要先对请求报头和请求行进行读取和分析,从中拿出必要的参数,如请求方法(GET/POST),统一资源定位符以及可能有的正文长度等相关信息。根据这些信息进行分析,如果是POST方法,说明请求报文中需要读取正文。
对于响应报文,其格式为状态行、响应报头、空行、响应正文。对于响应报文而言,其核心作用就是反馈给客户端有效的信息,所以响应的正文及正文长度是关键。如果对请求的处理使用的是非CGI机制,那反馈给客户端的就是一份静态资源,响应报头中的正文长度就是这份静态资源的长度。而使用CGI机制对请求进行处理时,则返回的正文内容应该是客户端申请的可执行程序对传递过来的参数的处理结果,正文长度也就应该是结果的长度。
3,从请求报文到响应报文:从接收到请求报文到反馈给客户端响应报文,需要经过一个读取请求、分析请求、构建响应、发送响应的过程。在这个过程中,需要做的几点关键判断是:
(1)请求是什么类型(决定是否需要读取正文)。
(2)请求一定带有相关的资源路径,但是否带参(如果是POST方法,正文就是参数,而如果是GET方法,则需要对统一资源定位符进行解析,如果是:资源路径?参数,亦即找到了?就说明带参,如果仅仅是资源路径,那就说明不带参。
(3)是否需要调用CGI机制,如果带参,那参数一定是需要服务器端的可执行程序进行处理的,那就一定要调用CGI机制,无论是GET还是POST方法,都需要。反之如果不带参,那就不需要调用CGI机制。
4,CGI机制:本项目借助父子进程的方式来实现HTTP服务器中的CGI机制。父子进程间使用匿名管道来建立链接,其中正文使用管道来进行传递,其余参数使用环境变量来传参。为了实现父进程中运行HTTP服务器,子进程中运行客户端申请的可执行程序,需要借助程序替换的手段来实现。与此同时,为了避免因程序替换造成子进程用户层文件描述符失效,还需要对子进程文件描述符进行重定向。