tinyhttpd源码分析

摘要:
if(管道(cgi_output)<}如果(管道(cgi_input)<0){cannot_execute(客户端);return;header;my($color)=“blue”;$color=$cgi->param('color')如果定义了$cgi->start_html(-title=>h1(“这是$color”);

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

  (1) startup函数

  这个函数的代码非常简单,其实就是简单创建一个server端的socket,让它绑定指定的端口,然后开始listen

  (2) accept_request函数

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

  (3) execute_cgi函数

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

  父进程中创建管道的代码:

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

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

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

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

免责声明:文章转载自《tinyhttpd源码分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android开发笔记(十六)——Activity的4种启动模式win10下安装Kafka下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

时间戳(Unix时间)

/// <summary> /// 时间戳与DateTime互转 /// </summary> public class UnixOfTimeHelper { /// <summary> /// 时间转unix时间戳 /// &...

【华为大咖分享】3.如何做Code Review 与 结对编程?

文:华为云DevCloud  庄表伟 这篇文章的起因是在《“敏捷中国史”交流群》里的一个争论,我希望能够通过这篇文章说明自己的一个观点:相对于结对编程,Code Review是一种更加合理与普适性的研发实践。 背景情况介绍 基于变更的Code Review 按照维基百科的定义,结对编程也是Code Review的一种形式。所以,当我想要把Code Revi...

build.xml配置编译打包过程(转)

工程目录如下,使用eclipse中的ant对此工程进行编译打包: MonServer       | --------src       |            |--------com       |            |--------log4j.properties       |        | --------config       |...

转载:SQL注入演示demo

网上看到的一个SQL注入的演示demo,很完整所以转载过来,分享给大家。先要感谢作者!!   作者:潘良虎链接:http://www.zhihu.com/question/22953267/answer/80141632来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 Web安全简史在Web1.0时代,人们更多是关注服务器端...

Qt开源作品30-农历控件

一、前言 农历控件在国产linux中必备的控件之一,毕竟要适应国人的习惯,你看win10系统的日历,现在点开来直接就有农历在上面,非常方便人性化,所以在很多用Qt做的项目中,也有农历控件的应用场景,而Qt自带的日历控件比较简单,仔细看过源码的人也只知道,其实就是一堆微调框,下拉框,表格组成的,于是打算借用此方法造一个农历控件,本控件的算法是倪大侠提供的,个...

uniapp支付宝小程序上传图片转base64

最近使用uniapp涉及到一个上传图片的功能,原本看官方文档api觉得没问题,正常开发, 1. 首先微信端没问题 uni.getFileSystemManager().readFile({ filePath: url, //选择图片返回的相对路径 encoding: "base64", //编码格式 succes...