C++开源代码学习的Tinyhttpd

   
想开始陆续研究有感谢兴趣之开源代码于是先挑一个代码量短的来接一下,写这篇博客的目的是记录下好学习之历程。Tinyhttpd算是一个小型的web服务器,浏览器与Web服务器之间的通信采用的凡Http,所以一律开始的切入点是HTTP协议,这里说一些只要发开HTTP通信的支出或看一下RFC中对不同版本HTTP的概念,以下原理部分都是自《后台开发:核心技术与用实践》中HTTP协议章节中推出来的,对后高感兴趣的校友可以扣押一下,讲述后台开发所待有所的技巧点同样准颇对的书。

一、HTTP协议

HTTP工作流程:

  于OSI七层模型中,HTTP是因TCP上的应用层协议而我们所说之HTTPS基于同处应用层的TLS、SSL协议层之上。HTTP默认的端口号为80,HTTPS默认的捧口号也443。在HTTP1.1吃(通过Connection头设置)默认在HTTP传输就后不断开TCP连接,在此之前的HTTP版本则默认是断开连接的,也就是说这次请和上次请求是不同之蝇头独TCP连接。一次等HTTP操作称为一个作业,其工作经过可以分为以下四步。

  (1)首先客户机与服务器需要建立连接 。 只要单击某个超级链接, HTTP
的做事就始 。
  (2)建立连接后,客户机发送一个要被服务器,请求方式的格式为:统一资源标识符(URL
)、协议版本号,后边是 MIME
信息(包括要修饰符、客户机信息以及可能的情节) 。

  (3)服务器收到请求后,给予对应的响应信息,其格式为一个态行,包括信息之说道版本号、一个打响或不当的代码,后边是
MTh伍信息(包括服务器信息、实体信息以及可能的情节) 。

  (4)客户端接收服务器所返的信经过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接

HTTP协议结构:

  HTTP 协议无论是请求报文还是应报文,都分为以下 4 单有 。

  (1)报文头( initial line ),上面的例子中之“ GET
http://www.baidu.com/favicon.icoHTTP/1.1 ”表示为此 GET 方法要
http://www.baidu.com/favicon. ic。这个文件,用的凡HTTP/1.1 协议。

  (2) 0 独或多单请求头( header line ),例如 Accept-Language: en

  (3)空行(作为 header lines 的结束) 。

  (4)可挑选的音体 。

  HTTP 协议是冲行之合计,每一样执 以 \r\n 作为分隔符 。
报文头通常表明报文的路(例如请求类型),且报文头只占一行
;请求头附带一些例外信息,每一个求求头占一实施,其格式为 name:value
,即坐分公司作为分隔; 空行也即盖一个 \r\n 分隔;可选 body
通常含数据,例如服务器返回的某部静态 HTML 文件之情 。

  HTTP请求方法:

  HTTP/ 1.1 协议中共定义了 9 种艺术(有时也被“动作”)来表 明
Request-URI 指定的资源的差操作方式,如下所陈述。

  ( 1 ) OPTIONS :返回服务器对一定资源所支持之 HTTP
请求方法;也得以用为 Web服务器发送“*”的求来测试服务器的功能性。

  ( 2) HEAD :向服务器需要和 GET
请求相平等的应,只不过响应体将不见面于归 。
这同一方可以在不必传输整个响应内容之情事下,就好得到包含在响应消息头着的正负信息
。该方法常用于测试超过链接的灵光,是否可以看,以及近年来是不是更新等信息

  ( 3) GET :向特定的资源发出请求 。 注意 : GET
方法不应该让用来产生“副作用”的操作着,例如在 web app .
中的使用,其中一个缘故是 GET 可能会见为网蜘蛛等随意访问 。

  ( 4 ) POST
:向指定资源提交数据开展拍卖要(例如提交表单或者达到污染文书) 。
数据为含有在呼吁求体中 。 POST
请求或会见促成新的资源的成立或者对已发出资源的改动 。

  ( 5 ) PUT :向指定资源职务及传其最新内容 。

  ( 6) DELETE : 请求服务器删除 Request-URI 所标识的资源 。

  ( 7 ) TRACE :回显服务器收到的呼吁,主要用以测试或确诊。

  ( 8) CONNECT: HTTP/ 1.1
协议被留给给能够以接连改呢管道方式的代理服务器 。

  ( 9) PATCH :用来将一些修改以叫某一样资源,该操作添加于规范盯C5789
中 。

  HTTP 服务器至少应当实现 GET 和 HEAD 方法,其他方式还是可选的 。
此外,除了上述方式,特定的 HTTP 服务器还会扩大自定义之计 。

  HTTP 常见的恳求头:

  于 HTTP/ l.l 协议中,所有的呼吁求头(除 Host
外)都是可选的,因为Host主要用以请求的服务器的IP地址与端口号,请求头有Host、Connection、Accept、Accept-Encoding、User-Agent、Cookie等,请求头太多这里就不排下了。

  HTTP回应报文:

  返回码由 3 各类数字组合,第一单数字定义了响应的类型,且发生 5
种可能的取值。

  ( 1 ) lxx :指示信息,表示请都接纳,继续处理。

  ( 2) 2xx :成功,表示请都于成功接收、理解 、 接受 。

  ( 3) 3xx :重定向,要就请求必须开展双重进一步的操作 。

  ( 4 ) 4xx :客户端错误,请求有语法错误或请求无法兑现。

  ( 5) 5xx :服务器端错误,服务器未能贯彻合法的请 。

  Date :表示消息发送的日,时间的叙说格式由 rfc822 定义 。

  Server : 指明 Web 服务器用来拍卖要的软件信息 。

  Accept-Ranges : Web
服务器表明自己是否收取获取其有实体的一样局部(比如文件的一致组成部分)的请求
。 bytes 代表接受, none 表示未接受。

  Vary: Web 服务器用该头部的情节告知 Cache
服务器,在啊法下才能够用本应所返的靶子应后续之乞求 。

  Content-Encoding : Web 服务器表明自己使用了呀压缩方法( gzip,
deflate)压缩响应中的目标。

  Content-Length: Web 服务器告诉浏览器自己应的对象的长度 。

  Content-Type: Web 服务器告诉浏览器自己应的对象的类型 。

二、CGI

  CGI ( Common Gateway Interface ,通用网关接口)是 HTTP
协议被尽重大之技艺有,有着不行替代的机要位置 。 CGI 是一个 Web
服务器提供信息服务的标准接口 。 通过 CGI 接口, Web
服务器即能收获客户端提交的音,转交给劳务器端的 CGI
程序进行处理,最后回来结果被客户端 。 组成 CGI 通信系统的凡少有些:
一部分凡 HTML
页面,就是在用户端浏览器上显示的页面;另一样部分则是运作在服务器上之 CG I
程序 。

  浏览器就需要指定执行服务器上之哪位CGI程序即使实施,一般情形下,服务器和
CGI
程序中是透过标准输入输出来进行数量传递的(就像tinyhttpd中调用CGI程序),而此过程要环境变茸的通力合作方可实现。环境变量在
CGI 中有着显要的身价,每个 CGI
程序只能处理一个用户要,所以于激活一个CGI程序进程时也创造了属该过程的环境变量,CGI程序会用Python、PERL、Shell、C或C++等语言来兑现。

  CGI 环境变量在 CGI 程序启动时初始化,在得了时销毁。当一个 CGI
程序不是为 HTTP 服务器调用时,它的环境变盘几乎是系环境变量的复制
。当是 CGI 程序为 HTTP 服务器调用时,它的环境变量就会多矣以下关于HTTP
服务器、客户端、 CGI 传输过程相当档。CGI 相关的环境变量有 3
种:与请求相关的环境变量、与服务器相关的环境变量和和客户端相关的环境变量,,详细呈现表
12-1 。

  

  CGI 工作原理:每当客户要 CGI 的早晚 Web
服务器即请求操作系统生成一个新的CGI
进程,该过程处理了要后离,下一个告来经常再也创新历程 。
当然,这样于访问量很少没有出现的气象中,可是当访问量增大且并发存在时时,这种艺术就无入了,于是便来了FastCGI。

  一般景象下, FastCGI 的全体办事流程如下所陈述。

  ( 1 ) Web Server 启动时载入 FastCGI 进程管理器( IIS ISAPI 或 Apache
Module ) 。

  ( 2 )FastCGI 进程管理器自身初始化,启动多只 CGI 进程并等候来自 Web
服务器的连接 。

  ( 3 )当客户端请求到达 Web Server 时, FastCGI
进程管理器选择并连到一个 FastCGI进程 。 Web 服务器将 CGI
环境变量和标准输入发送至 FastCGI 进程 。

  ( 4) FastCGI 子进程就处理后用规范输出以及错误信息从平连接返回 Web
Server。当FastCGI 子进程关闭连接时,请求虽叫喻处理就 。 FastCGI
进程就等待并处理来自FastCGI 进程管理器(运行于 Web
服务器中)的下一个连接 。

三、tinyhttpd解析

  关于tinyhttpd的代码解析的博客太多了,流程以及注释都讲述的老大详细,随便搜个tinyhttpd解析就有无数博客出现,这里要写一下和好当圈这卖源码时欠的知识点,因为自几从不linux下编程的阅历,所以针对linux下用的Glib库调用不顶熟悉,TCP协议栈也是自我特拘留了了轻量级Lwip的源码。

  1.bind函数当传入的port为0时是会见随随便便分配一个端口号,所以tinyhttpd中才见面时有发生展示随机的捧口号,getsockname函数获取套接字之地方将动态分配的端口号值取出。

  

  2.int stat(const char *file_name, struct stat
*buf);通过文件名filename获取文件信息,并保留于buf所依赖的结构体stat中,S_IXUSR:文件所有者拥有可尽权,S_IXGRP:用户组具可尽权,S_IXOTH:其他用户具可读博权限。

  3.int pipe(int filedes[2]);

  返回值:成功,返回0,否则回-1。参数数组包含pipe使用的个别个文件的叙说称。fd[0]:读管道,fd[1]:写管道。

  必须以fork()中调用pipe(),否则子进程不会见连续文件讲述吻合。两个过程不同台享祖先进程,就无可知动用pipe。但是好运用命名管道。

  pipe(cgi_output)执行成功后,cgi_output[0]:读通道
cgi_output[1]:写通道

  

   int dup2(int oldfd,int newfd);函数的作用是复制文件讲述吻合。

  4.fork函数,创建一个子进程,fork函数之后的有是因为在fork函数执行了后,如果创建新过程成功,则产出些微只过程,一个是子进程,一个是爸爸进程。在旁进程遭到,fork函数返回0,在父亲进程中,fork返回新创建子进程的历程ID,有时空更看fork源码是什么兑现之。

  5.execl函数履行,第一参数path字符指针所倚为如执行的文件路径,后面跟着可变换参数,这里说一些由GCC使用AAPCS规范,可转移参数的实现小于四独底语句是打r0-r3沾,大于四独的言辞就使由栈中获取参数。 

  6.pid_t waitpid(pid_t pid, int * status, int
options);会临时平息目前经过的尽, 直到起信号到或子进程结束. 

  以编辑博客边看tinyhttpd,目前和好之不够明亮的函数就点几乎独,有空再望它的源码实现。