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

系列文章:
自己动手写http服务器(一) -- UNIX C 网络编程
自己动手写http服务器(二) -- 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
00000130: 0d0a 4163 6365 7074 2d45 6e63 6f64 696e  ..Accept-Encodin
00000140: 673a 2067 7a69 702c 2064 6566 6c61 7465  g: gzip, deflate
00000150: 2c20 6272 0d0a 4163 6365 7074 2d4c 616e  , br..Accept-Lan
00000160: 6775 6167 653a 207a 682d 434e 2c7a 683b  guage: zh-CN,zh;
00000170: 713d 302e 382c 6c61 3b71 3d30 2e36 2c64  q=0.8,la;q=0.6,d
00000180: 613b 713d 302e 340d 0a0d 0a              a;q=0.4....

左侧是接收的数据原始二进制流,右侧是对应的ASCII码;

可见浏览器默认使用的http协议是 HTTP/1.1,其头信息肯定是文本(ASCII编码);

(2)捕捉 https 协议的数据包

通过命令:

nc  -l  127.0.0.1  8888  >  https.data

在浏览器中输入 url 地址 https://127.0.0.1:8888 ,即可获得浏览器发送给服务器的数据,内容如下:

00000000: 1603 0100 c2ae 0100 00c2 aa03 0328 6fc2  .............(o.
00000010: a227 0f31 c392 c388 c392 42c2 8dc2 9dc2  .'.1......B.....
00000020: 8275 c297 2324 c38f 484d 75c2 8b23 5bc2  .u..#$..HMu..#[.
00000030: aac3 98c3 a17c 0d70 6cc2 be00 001c 2a2a  .....|.pl.....**
00000040: c380 2bc3 802f c380 2cc3 8030 c38c c2a9  ..+../..,..0....
00000050: c38c c2a8 c380 13c3 8014 00c2 9c00 c29d  ................
00000060: 002f 0035 000a 0100 0065 c2aa c2aa 0000  ./.5.....e......
00000070: c3bf 0100 0100 0017 0000 0023 0000 000d  ...........#....
00000080: 0014 0012 0403 0804 0401 0503 0805 0501  ................
00000090: 0806 0601 0201 0005 0005 0100 0000 0000  ................
000000a0: 1200 0000 1000 0e00 0c02 6832 0868 7474  ..........h2.htt
000000b0: 702f 312e 3175 5000 0000 0b00 0201 0000  p/1.1uP.........
000000c0: 0a00 0a00 086a 6a00 1d00 1700 182a 2a00  .....jj......**.
000000d0: 0100 0a                                  ... 

可见,https协议的头信息是二进制数据流而非文本;

本文只对 http1.1 协议进行分析;

(3)分析 http Get请求数据包

浏览器发送到服务器端的请求数据为:

GET / HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
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
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

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

<method> <request-URL> <version>

每个字段用空格分隔;

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

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

如果在浏览器中输入 http://127.0.0.1:8888/xxx/yy?name=abc&age=23 则 request-URL 的值将是 * /xxx/yy?name=abc&age=23 * ;

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

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

首先,我们创建一个html文件,文件地址为 :
/home/hbfeng/Code/Year2017/Mon07/Day19/x.html

文件内容为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <form action="http://127.0.0.1:8888" method="POST">
        color:<input type="text" name="color">
        <input type="submit" value="提交" />
    </form>
</body>
</html>

之后,开启服务器 :

nc  -l  127.0.0.1  8888  >  post.dat

在浏览器中输入 :
file:///home/hbfeng/Code/Year2017/Mon07/Day19/x.html

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

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服务器就可以将数据包进行解析,并动态生成页面发送给浏览器;

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

tinyhttpd的工作流程

反馈给客户端的数据格式

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

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

HTTP/1.0 400 BAD REQUEST
Content-type: text/html

<!DOCTYPE>
<html>
  <!-- html内容 -->
  ... ... 
</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程序的语言,另外,像 PythonRubyC/C++PHP 等也可以实现CGI,甚至是 Shell脚本 文件也能胜任该任务;

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

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

参考

HTTP协议入门

关于HTTP协议,一篇就够了

HTTP/1.1 Header Field Definitions

通用网关接口

完!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 一、概念(载录于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434阅读 8,328评论 6 152
  • Http协议详解 标签(空格分隔): Linux 声明:本片文章非原创,内容来源于博客园作者MIN飞翔的HTTP协...
    Sivin阅读 5,201评论 3 82
  • 前言:最近发现自己在网络相关这一块基础很是欠缺,所以准备花时间了解一下,本文主要是讲http协议的一些基础,和一些...
    justCode_阅读 2,092评论 0 23
  • 深入浅出HTTP协议(WEB开发和面试必备) 1.基础概念篇 a.简介 HTTP是Hyper Text Trans...
    半世韶华忆阑珊阅读 1,211评论 0 7
  • 本文整理自MIN飞翔博客 [1] 1. 概念 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或...
    HoyaWhite阅读 2,634评论 2 20