基于HTTP协议实现的小型web服务器 云服务


咱们先了解一下这个项目最终能达到的一个目标,而后以这个来进行项目的分析:  html

这里写图片描述

GET方法使用的是带参数的URL,即传递的参数会使用?链接在资源路径后边;POST方法使用的是不带参数的URL,它的参数是经过http请求报头中的请求消息体传递给服务器的。
sql

这里写图片描述响应报头中的状态码和状态码描述,例如:当请求的资源不存在时,会收到“404 NotFound”的页面,404就是状态码,“NotFound”就是状态码描述,即请求的文件不存在。
shell

2、服务器实现的基本思路

一、http协议是基于TCP通讯的协议,所以,实现web服务器的第一步至少要能实现两个主机不一样进程之间的TCP通讯。  数据库

二、接下来的部分就是比较主要的处理逻辑了,当服务器收到请求后,首先应该分析请求方法(由于web服务器是要支持cgi的,但请求方法不一样处理cgi也不一样,这里咱们只处理GET和POST方法)。  浏览器

三、当方法肯定后,应该拿到请求的URL,这一步是为了咱们后边能处理GET和POST方法的cgi(GET和POST的参数位置不一样,GET的参数在URL中,POST的参数在请求正文中)  服务器

四、判断资源是否存在,若是存在,判断这个资源是一个目录、普通文件仍是一个可执行程序。以前几步咱们已经提取到URL以及参数。GET方法:若是没有参数,就直接将请求的资源返回(即进入非cgi模式运行);不然,进入cgi模式内部运行;只要是POST方法就须要支持cgi:直接进入cgi函数内部运行。 

非cgi模式:
进入非cgi模式时必定是GET方法且没有参数,此时进入echo_www()函数内部便可,该函数会将所请求的资源以html的格式返回给浏览器。

cgi模式: 

这里写图片描述

上述这张图描述了运行cgi时的过程,首先服务器要从浏览器上读取参数,而后须要fork出一个子进程进行cgi部分的处理,父进程经过环境变量的方式将参数转交给子进程,子进程运行完成后,将结果交给父进程,父进程再将数据输出给浏览器。在这个过程当中能够将父进程看做一个所谓的中间量,只进行了参数的转交,所以能够将子进程的输入输出文件描述符进行重定向,即子进程直接与浏览器“联系”。

下面总结出父子进程内部各自须要干的事情:

这里写图片描述

3、错误处理

错误处理这部分的实现能够参考echo_www()函数,但须要改变响应的消息报头的格式,即改变状态码,状态码描述,以及返回的页面。例如当请求的资源不存在时,服务器须要返回给浏览器一个默认的404页面,告诉客户请求的资源不存在。效果如图: 

这里写图片描述

4、项目文件

这里写图片描述

目录: 

 cgi:运行cgi部分的实现代码 

 conf:配置文件,存放须要绑定的服务器的ip和port 

log:shell的日志文件以及http错误处理的日志文件 

 lib:mysql须要的lib库 

sql_client:mysql部分的API及CGI实现 

wwwroot:web服务器工做的根目录,包含各类资源页面(例如默认的index.html页面,差错处理的404页面),以及执行cgi的可执行程序 

文件: 

configure.sh:sheel脚本,运行该shell脚本后须要自动生成Makefile文件 

http_ctl.sh:服务器控制脚本,须要实现服务器的启动、暂停以及从新启动 

httpd.pid:与http_ctl.sh配合使用。若是把服务器变成守护进程在后台运行,从新启动时就须要检测服务器是否启动,该文件存放服务器启动之后的进程id  

httpd.h:服务器的方法声明 

 httpd.c:方法实现 

 main.c:服务器的主逻辑 


5、实现结果

请求资源存在: 

这里写图片描述

运行cgi后: 

这里写图片描述

6、源码:

https://github.com/lybb/Linux/tree/master/httpd

附: 

 这里是我遇到的一些问题,粘出来,也多是你遇到的问题:

一、本地环回测试ok,Linux下的浏览器测试也能够,但不能接外部的浏览器访问(没有设置桥接模式)嗯~要是在外部浏览器测试的话千万别忘记关闭防火墙 

二、服务器应答时,没有将html格式的页面发送,而是将底层的实现代码展现在浏览器,而且在调试时将原本要打印的调试信息会打印到网页上(在回应空行时将send指望发送的数值写的太大,原本只须要发送两个字节的内容) 解决:先检查代码,思路正确,在容易出现问题的地方加入调试信息,最后将问题定位在echo_www()函数内 

三、不能显示图片(这个问题是没有将全部发送的状况考虑彻底,只考虑到目录、可执行程序,但没有考虑到若是请求的是一个路径明确的普通文件) 解决:测试请求一个路径明确的test.html文件,加入调试信息 ,将问题定位在:若是请求的资源存在,应该如何处理。对于普通文件,找到后并回显给浏览器;若是是目录,应答的是默认页面;若是是可执行程序,执行后返回结果 

四、能显示图片后,但显示的不完整(缘由:echo_www中,指望读取一行信息的line值过小,不能存下一张图片) 

五、运行cgi模式时,每次提交数据并进行submit后都会自动出现提醒下载的页面 缘由:在响应报头中,将Content-Type中的”text”写成”test”。而浏览器对于不能识别或解析的实体,都会提醒用户下载。

相关文章
相关标签/搜索