2.1 执行流程
上图展示了tiny httpd大致的执行流程:
①main()函数首先调用了startup()函数开启了一个TCP服务器端口。
②该端口在收到请求后,main()函数会创建一个线程,执行accept_request()函数处理请求
③accept_request()函数会首先解析请求行,如果该请求是一个非GET、POST请求,那么向客户端返回一个501(Not Implemented)响应。
④如果该请求是GET或POST请求,那么accept_request()函数会继续执行。如果请求的文件不存在,将返回一个404(Not Found)响应。
⑤如果请求的文件存在,服务器会判断其是HTML静态文件还是CGI程序。如果是HTML静态文件,则直接返回它。如果是CGI程序,则先解析请求头,如果解析失败,返回400(Bad Request)响应;解析成功,则执行CGI程序,返回程序执行结果。
2.2 主要函数浅析
在详细地分析每个函数之前,我们先来大致地了解一下他们的作用。
2.2.1 startup()
startup()开启了一个TCP服务器。总所周知,HTTP协议是基于TCP协议的。这里有一个重要的网络编程概念 —— socket,后面我们将花费大量篇幅去讲解它,它是整个网络编程的基础。
2.2.2 accept_request()
accept_request()负责处理HTTP请求,是整个服务器的核心。tiny httpd每收到一个请求,就会创建一个线程执行accept_request()函数。后面的几个主要功能函数都是在accept_request()中被调用的。
2.2.3 unimplemented()
HTTP协议是一个相当宽松的协议,其规范只要求我们实现GET和HEAD方法,其他的方法都是可选的。所以当服务器收到一个自己没有实现的方法时,HTTP协议规定服务器返回一个501(Not Implemented)响应,来告诉客户端当前服务器不支持该方法。tiny httpd是J.David Blackstone在1999年出于学习目的完成的,所以它支持GET和POST方法。当客户端请求的方法是非GET、POST方法时,tiny httpd就会调用unimplemented()返回一个501响应。
2.2.4 not_found()
Not Found是我们浏览网页时最常见的错误,它表示服务器找不到我们所请求的资源。当然,HTTP协议并未强制规定只能在此种情况下使用Not Found响应,所以当服务器不想返回某个资源给客户端,同时又不想给出具体理由时,也可以返回一个404响应“敷衍”客户端。tiny httpd中的not_found()函数便是用来返回404响应的。
2.2.5 serve_file()
serve_file()负责将服务器上的静态资源返回给客户端。常见的静态资源有HTML文档、CSS文件等。
2.2.6 execute_cgi()
当客户端请求的是一个CGI程序时,tiny httpd就会调用execute_cgi()。这里我们将接触到另一个很重要的概念 —— CGI,其全称是Common Gateway Interface(通用网关接口)。实际上,如今CGI已基本被淘汰,之所以说它重要,是因为如今的WSGI和Servlet等协议的设计思想都源自于CGI。CGI的主要作用是根据请求的上下文,动态地生成响应。其具体内容我们将在后续的博客中探究。
2.2.7 bad_request()
HTTP协议对请求的格式有一定的要求,如果服务器收到了一个格式错误的请求,HTTP协议规定服务器返回一个400(Bad Request)响应。bad_request()在tiny httpd中就扮演了这一角色。
2.3 总结
熟悉HTTP协议和web开发的同学应该知道我在说什么,不熟悉的同学可能已经是这个状态了: