写了一个简单的CGI Server

之前看过一些开源程序的源码,也略微知道些Apache的CGI处理程序架构,于是用了一段时间,用C写了一个简单的CGI Server,代码算上头文件,一共1200行左右,难度中等偏上。麻雀虽小,五脏俱全。如果把程序里所涉及的HTTP协议,Linux下POSIX编程等等搞清楚,我想找工作中肯定是有足够的竞争力的,当然我也只是皮毛而已,不再班门弄斧了,下面简单的说下程序流程吧。

再说程序流程之前,我先简单说下CGI吧,CGI这个东西比较老了,N年之前,没有PHP JSP等等动态脚本之前,这个是非常火的。只要能支持输入输出的程序,都可以编写CGI脚本,比如Apache就集成了CGI服务器功能,你可以使用Python编写简单的CGI脚本,可以参照前几天我发的文章,点击此处,现在CGI 脚本基本上使用的比较少了,但是在一些对效率要求比较高的设计里还是可以看到一些身影,比如腾讯的QQ相册,QQ空间里就可以看到(你可以打开QQ空间,查看源码-查找CGI),他们的脚本应该是C/C++编写的,效率,你懂的,如果你想更多的了解CGI脚本相关,可以点击此处,推荐了解一些,但是不值得深入学习,那个精力不如学习PHP/Python了。。。

其实说白了,CGI 扮演的就是在服务器和特定解释器之间输入输出协议的角色,每个来自用户的请求,Web服务器都会唤起特定语言解释器的命令行,执行CGI脚本。

现在来介绍下此CGI Server,我不想长篇大论了,一幅图来描述其执行过程(字比较丑,凑合看吧),具体看代码吧:

如果你比较理解HTTP协议,大部分都没有难点,中文URL编码这个可以看上一篇文章,可能唯一的难点是管道部分,这个使用了经典的fork-exece模型,关于管道,一张图能很好的解释:

不过程序中使用了双管道,读写模型,如果你对此不理解,可以翻阅《Unix环境高级编程》。
如果你对HTTP不太了解,参考链接里的两篇文章,能帮助你更好的了解HTTP协议,其实HTTP1.1里面的难点,理解以下几句话就足够了:

http协议规定头必然有2个连续的”\r\n”,就像Cookie后面就跟了2个\r\n,所以读取请求头的时候只要读到\r\n\r\n,那么前面就是头,后面就是实体。实体大小在上面有一个Content-Length标记。所以从\r\n\r\n后面读Content-Length大小后就结束了。所以服务端一般是1、判断状态码,http协议规定1xx 204 304肯定不包括实体,所以读到\r\n\r\n就不用再读;2、判断没有Content-Length;3、判断有没有chunked。有Content-Length直接读,而chunked的最后7个一定是\r\n0\r\n\r\n。

chunked编码,这种编码一般是gzip压缩的

HTTP/1.1 200 OK 
Cache-Control: private 
Content-Type: text/html; charset=utf-8 
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 2.0
X-AspNet-Version: 4.0.30319 
Set-Cookie: Set-Cookie: X-Powered-By: ASP.NET 
ntCoent-Length: 166137
Content-Encoding: gzip 
Transfer-Encoding: chunked 



2D23 
...........}.s.G.......j....*u......y....%...;QO.M.[....3..,...
.!..O....H-."v..>.............=YY 

 
在处理chunked时候,像上面chunked\r\n\r\n后面是实体,第一行2D23就是一chunk的大小所以在2D23\r\n后面开始读2D23个然后会紧跟着\r\n,然后后面就是下一chunk的大小,直到最后一chunk是0大小。实体结束,最后再来一个\r\n。也就是说chunked的最后7个一定是\r\n0\r\n\r\n,本来判断读到\r\n0\r\n\r\n就结束应该没问题,但是为了保险起见,还是一次一次的读大小值再读取指定的大小数据。

另外,此代码里有部分缺陷,一是我急于完成,某些结构设计不合理,所以可扩展性比较差。第二,有少部分内存泄漏,懒得修改了。毕竟,我也得忙着找工作,时间比较紧张,但是总的来说,如果你想找后台开发相关的职位,如果你没有更好的项目经验,此代码如果你能读懂,写到简历上,面试官肯定会问你的。

能力和精力有限,希望能对你们有所帮助 ^-^

注:学生时代的作品,此代码已废弃,等我有空做个更好的 ^_^

参考链接:

1.http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html

2.http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html

3.http://blog.csdn.net/laotse/article/details/5903651