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核心的內容就結束了。

相關文章
相關標籤/搜索