天天看点

服务器封包协议号,自己动手写http服务器(二) -- http协议分析

要编写一个 http 服务器,第一步就是分析 http 协议格式,之后才能对发送过来的http数据包进行正常解析,并返回正确的数据包;

Http协议包的格式

首先,让我们用 netcat 捕获浏览器发送给服务器的数据包,来见一见其庐山真面目。

(1)捕捉 http 协议的数据包

通过命令:

nc -l 127.0.0.1 8888 > http.data

开启本地的 8888 号端口,在浏览器中输入 url 地址 http://127.0.0.1:8888 ,浏览器将会发送给一个Get请求给nc,nc将接收到的数据写入文件 http.data , 接收到的内容如下:

00000000: 4745 5420 2f20 4854 5450 2f31 2e31 0d0a GET / HTTP/1.1..

00000010: 486f 7374 3a20 3132 372e 302e 302e 313a Host: 127.0.0.1:

00000020: 3838 3838 0d0a 436f 6e6e 6563 7469 6f6e 8888..Connection

00000030: 3a20 6b65 6570 2d61 6c69 7665 0d0a 5570 : keep-alive..Up

00000040: 6772 6164 652d 496e 7365 6375 7265 2d52 grade-Insecure-R

00000050: 6571 7565 7374 733a 2031 0d0a 5573 6572 equests: 1..User

00000060: 2d41 6765 6e74 3a20 4d6f 7a69 6c6c 612f -Agent: Mozilla/

00000070: 352e 3020 2858 3131 3b20 4c69 6e75 7820 5.0 (X11; Linux

00000080: 7838 365f 3634 2920 4170 706c 6557 6562 x86_64) AppleWeb

00000090: 4b69 742f 3533 372e 3336 2028 4b48 544d Kit/537.36 (KHTM

000000a0: 4c2c 206c 696b 6520 4765 636b 6f29 2043 L, like Gecko) C

000000b0: 6872 6f6d 652f 3539 2e30 2e33 3037 312e hrome/59.0.3071.

000000c0: 3131 3520 5361 6661 7269 2f35 3337 2e33 115 Safari/537.3

000000d0: 360d 0a41 6363 6570 743a 2074 6578 742f 6..Accept: text/

000000e0: 6874 6d6c 2c61 7070 6c69 6361 7469 6f6e html,application

000000f0: 2f78 6874 6d6c 2b78 6d6c 2c61 7070 6c69 /xhtml+xml,appli

00000100: 6361 7469 6f6e 2f78 6d6c 3b71 3d30 2e39 cation/xml;q=0.9

00000110: 2c69 6d61 6765 2f77 6562 702c 696d 6167 ,image/webp,imag

00000120: 652f 6170 6e67 2c2a 2f2a 3b71 3d30 2e38 e/apng,**;q=0.8

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.8,la;q=0.6,da;q=0.4

对于HTTP报文来说,第一行为报文的起始行,格式为

每个字段用空格分隔;

在该例子中, method 为 GET ,request-URL 为 / ,version 为 HTTP/1.1 ;

在这里,因为我们只是在浏览器中输入一个ip地址及端口号,默认的请求资源为 / ;

如果在浏览器中输入

(4)捕获 http Post 请求数据包

下面我们来捕获以下Post的请求包,看看其与Get请求包的不同;

首先,我们创建一个html文件,文件地址为 :

/home/hbfeng/Code/Year2017/Mon07/Day19/x.html

文件内容为:

Document

color:

之后,开启服务器 :

nc -l 127.0.0.1 8888 > post.dat

在浏览器中输入 :

file:///home/hbfeng/Code/Year2017/Mon07/Day19/x.html

可以出现如下页面,在文本框中填入内容,点击 提交 即可获得一个Post数据包:

服务器封包协议号,自己动手写http服务器(二) -- http协议分析

POST数据获取

Post数据包的内容如下:

POST / HTTP/1.1

Host: 127.0.0.1:8888

Connection: keep-alive

Content-Length: 12

Cache-Control: max-age=0

Origin: null

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36

Content-Type: application/x-www-form-urlencoded

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.8,la;q=0.6,da;q=0.4

color=yellow

与Get请求的数据相比,Post数据包多出了以下我们后续编写代码时需要使用的内容:

Content-Length: 12 : 表示HTTP正文的大小。POST请求将数据以URL编码的形式放在HTTP正文中,字段形式为 fieldname=value,用&分隔每个字段;

HTTP信息头与HTTP正文之间有一行空行;

HTTP中有表单内容 color=yellow ,正好等于 Content-Length 的长度;

服务器的工作流程

知道了浏览器给我们发送的数据格式以后,我们的http服务器就可以将数据包进行解析,并动态生成页面发送给浏览器;

服务器的大致工作流程如下图所示:

服务器封包协议号,自己动手写http服务器(二) -- http协议分析

tinyhttpd的工作流程

反馈给客户端的数据格式

知道了服务器的运行流程,我们需要知道浏览器希望从服务器端得到什么格式的数据;

服务器按照HTTP协议返回数据给客户端,如响应码为400,返回的内容为:

HTTP/1.0 400 BAD REQUEST

Content-type: text/html

... ...

每一行最后都跟 \r\n ,表示一行的结束;

第一行的3个参数用空格隔开,第一个参数说明服务器所使用的http协议为 HTTP/1.0 ,第二个参数是一个返回码,第三个参数是对返回码的解释;

第二行声明的是http正文内容的类型,text/html 表示正文是一个html文件的内容,浏览器将其解释并显示,如果是 text/plain 表示正文是纯文本,浏览器直接将内容显示,不需要解释、渲染等操作;

之后的空行表示http信息头结束;

空行之后的内容即为http正文;

动态生成Web页面技术

CGI (Common Gateway Interface,通用网关接口) :一种重要的互联网技术,是指根据浏览器发送过来的请求,服务器执行一定的动作,如数据库查询、系统信息查询等,甚至可以让服务器删除某些文件,之后生成对应的内容返回给浏览器以显示执行结果;

可以将CGI理解为通过浏览器就可以让服务器执行某些在服务器端已经定义好的功能,实现远程调用 ;

CGI是这种技术的定义,而其实现方式多种多样,如 Perl 是一个广泛被用来编写CGI程序的语言,另外,像 Python、Ruby、C/C++、PHP 等也可以实现CGI,甚至是 Shell脚本 文件也能胜任该任务;

CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。

在下一篇中,我们就来根据上面的流程图来实现一个小型的http服务器;

参考

完!