tinyhttpd源码分析

  咱们常常使用网页,做为开发人员咱们也部署过httpd服务器,好比开源的apache,也开发过httpd后台服务,好比fastcgi程序,不过对于httpd服务器内部的运行机制,却不是很是了解,前几天看见tinyhttpd,只有短短500行左右的代码,就实现了一个简单的httpd服务器的基本功能,这种tiny程序,其实对于咱们了解基本核心有必定的帮助,能够经过分析其代码,了解构建一个简单的httpd服务器须要的基本元素。html

  (1) startup函数apache

  这个函数的代码很是简单,其实就是简单建立一个server端的socket,让它绑定指定的端口,而后开始listen浏览器

  (2) accept_request函数服务器

  此函数中首先解析客户端的请求方式,是GET,仍是POST,tinyhttpd只能处理这2种请求,若是都不是,就返回错误。而后解析请求的url,而后对应到服务器中tinyhttpd中htdocs目录下的文件,检查文件状态,若是文件不存在,那么返回错误。若是文件存在,是GET方法时,tinyhttpd直接返回此文件,一般是html。若是是POST,那么会执行对应的.cgi文件,tinyhttpd中的CGI文件,是用PERL脚本实现的。socket

  (3) execute_cgi函数函数

  此函数中就是如何执行CGI脚本的地方,首先仍是将POST部分的数据解析出来,而后fork一个子进程去执行CGI脚本,这里有一个小的技巧,就是tinyhttpd使用了管道来让执行CGI脚本的子进程,经过标准输出写入和父进程的管道中,父进程在fork以后,读取此管道中的数据,而后返回给客户端。ui

  父进程中建立管道的代码:url

 if (pipe(cgi_output) < 0) {
  cannot_execute(client);
  return;
 }
 if (pipe(cgi_input) < 0) {
  cannot_execute(client);
  return;
 }

  这里建立了2个管道,每一个管道都有一个写端,一个读端。spa

  子进程是经过下面代码执行的:code

execl(path, path, NULL);

  父进程中,读取管道中的内容:

while (read(cgi_output[0], &c, 1) > 0)
   send(client, &c, 1, 0);

  color.cgi代码:

#!/usr/bin/perl -Tw

use strict;
use CGI;

my($cgi) = new CGI;

print $cgi->header;
my($color) = "blue";
$color = $cgi->param('color') if defined $cgi->param('color');

print $cgi->start_html(-title => uc($color),
                       -BGCOLOR => $color);
print $cgi->h1("This is $color");
print $cgi->end_html;

  单独在控制台下运行的结果是:

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>BLUE</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body bgcolor="blue">
<h1>This is blue</h1>
</body>
</html>

  也就是说,tinyhttpd经过子进程运行PERL的CGI脚本,而后脚本输出了一个HTML,这个HTML内容经过父子进程之间的管道进程消息传递,父进程读取管道中的内容发送给浏览器。

  不过咱们从代码中只看到了设置环境变量putenv的部分,若是是POST方法,并无看见设置参数的部分,其实这部分代码,是在fork以后,parent中经过for循环,将content_length长的content经过管道write给了子进程的标准输入,这也就是为何在fork子进程以前先建立了2个管道的缘由。

  这样,整个tinyhttpd核心的内容就结束了。

相关文章
相关标签/搜索