自己動手寫http服務(wù)器(二) -- http協(xié)議分析

系列文章:
自己動手寫http服務(wù)器(一) -- UNIX C 網(wǎng)絡(luò)編程
自己動手寫http服務(wù)器(二) -- http協(xié)議分析
自己動手寫http服務(wù)器(三) -- 代碼實(shí)現(xiàn)

要編寫一個(gè) http 服務(wù)器,第一步就是分析 http 協(xié)議格式,之后才能對發(fā)送過來的http數(shù)據(jù)包進(jìn)行正常解析规哪,并返回正確的數(shù)據(jù)包瀑构;

Http協(xié)議包的格式

首先,讓我們用 netcat 捕獲瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù)包,來見一見其廬山真面目。

(1)捕捉 http 協(xié)議的數(shù)據(jù)包

通過命令:

nc  -l  127.0.0.1 8888  >  http.data

開啟本地的 8888 號端口,在瀏覽器中輸入 url 地址 http://127.0.0.1:8888 冯键,瀏覽器將會發(fā)送給一個(gè)Get請求給nc,nc將接收到的數(shù)據(jù)寫入文件 http.data , 接收到的內(nèi)容如下:

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....

左側(cè)是接收的數(shù)據(jù)原始二進(jìn)制流庸汗,右側(cè)是對應(yīng)的ASCII碼惫确;

可見瀏覽器默認(rèn)使用的http協(xié)議是 HTTP/1.1,其頭信息肯定是文本(ASCII編碼)夫晌;

(2)捕捉 https 協(xié)議的數(shù)據(jù)包

通過命令:

nc  -l  127.0.0.1  8888  >  https.data

在瀏覽器中輸入 url 地址 https://127.0.0.1:8888 雕薪,即可獲得瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù),內(nèi)容如下:

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協(xié)議的頭信息是二進(jìn)制數(shù)據(jù)流而非文本所袁;

本文只對 http1.1 協(xié)議進(jìn)行分析;

(3)分析 http Get請求數(shù)據(jù)包

瀏覽器發(fā)送到服務(wù)器端的請求數(shù)據(jù)為:

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報(bào)文來說凶掰,第一行為報(bào)文的起始行燥爷,格式為

<method> <request-URL> <version>

每個(gè)字段用空格分隔;

在該例子中懦窘, method 為 GET 前翎,request-URL 為 / ,version 為 HTTP/1.1 畅涂;

在這里港华,因?yàn)槲覀冎皇窃跒g覽器中輸入一個(gè)ip地址及端口號,默認(rèn)的請求資源為 / 午衰;

如果在瀏覽器中輸入 http://127.0.0.1:8888/xxx/yy?name=abc&age=23 則 request-URL 的值將是 * /xxx/yy?name=abc&age=23 * 立宜;

(4)捕獲 http Post 請求數(shù)據(jù)包

下面我們來捕獲以下Post的請求包冒萄,看看其與Get請求包的不同;

首先橙数,我們創(chuàng)建一個(gè)html文件尊流,文件地址為 :
/home/hbfeng/Code/Year2017/Mon07/Day19/x.html

文件內(nèi)容為:

<!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>

之后,開啟服務(wù)器 :

nc  -l  127.0.0.1  8888  >  post.dat

在瀏覽器中輸入 :
file:///home/hbfeng/Code/Year2017/Mon07/Day19/x.html

可以出現(xiàn)如下頁面灯帮,在文本框中填入內(nèi)容崖技,點(diǎn)擊 提交 即可獲得一個(gè)Post數(shù)據(jù)包:

POST數(shù)據(jù)獲取

Post數(shù)據(jù)包的內(nèi)容如下:

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請求的數(shù)據(jù)相比,Post數(shù)據(jù)包多出了以下我們后續(xù)編寫代碼時(shí)需要使用的內(nèi)容:

  • Content-Length: 12 : 表示HTTP正文的大小钟哥。POST請求將數(shù)據(jù)以URL編碼的形式放在HTTP正文中迎献,字段形式為 fieldname=value,用&分隔每個(gè)字段瞪醋;

  • HTTP信息頭與HTTP正文之間有一行空行忿晕;

  • HTTP中有表單內(nèi)容 color=yellow 装诡,正好等于 Content-Length 的長度银受;

服務(wù)器的工作流程

知道了瀏覽器給我們發(fā)送的數(shù)據(jù)格式以后,我們的http服務(wù)器就可以將數(shù)據(jù)包進(jìn)行解析鸦采,并動態(tài)生成頁面發(fā)送給瀏覽器宾巍;

服務(wù)器的大致工作流程如下圖所示:

tinyhttpd的工作流程

反饋給客戶端的數(shù)據(jù)格式

知道了服務(wù)器的運(yùn)行流程,我們需要知道瀏覽器希望從服務(wù)器端得到什么格式的數(shù)據(jù)渔伯;

服務(wù)器按照HTTP協(xié)議返回?cái)?shù)據(jù)給客戶端顶霞,如響應(yīng)碼為400,返回的內(nèi)容為:

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

<!DOCTYPE>
<html>
  <!-- html內(nèi)容 -->
  ... ... 
</html>

每一行最后都跟 \r\n 锣吼,表示一行的結(jié)束选浑;

第一行的3個(gè)參數(shù)用空格隔開,第一個(gè)參數(shù)說明服務(wù)器所使用的http協(xié)議為 HTTP/1.0 玄叠,第二個(gè)參數(shù)是一個(gè)返回碼古徒,第三個(gè)參數(shù)是對返回碼的解釋;

第二行聲明的是http正文內(nèi)容的類型读恃,text/html 表示正文是一個(gè)html文件的內(nèi)容隧膘,瀏覽器將其解釋并顯示,如果是 text/plain 表示正文是純文本寺惫,瀏覽器直接將內(nèi)容顯示疹吃,不需要解釋、渲染等操作西雀;

之后的空行表示http信息頭結(jié)束萨驶;

空行之后的內(nèi)容即為http正文;

動態(tài)生成Web頁面技術(shù)

CGI (Common Gateway Interface艇肴,通用網(wǎng)關(guān)接口) :一種重要的互聯(lián)網(wǎng)技術(shù)腔呜,是指根據(jù)瀏覽器發(fā)送過來的請求判莉,服務(wù)器執(zhí)行一定的動作,如數(shù)據(jù)庫查詢育谬、系統(tǒng)信息查詢等券盅,甚至可以讓服務(wù)器刪除某些文件,之后生成對應(yīng)的內(nèi)容返回給瀏覽器以顯示執(zhí)行結(jié)果膛檀;

可以將CGI理解為通過瀏覽器就可以讓服務(wù)器執(zhí)行某些在服務(wù)器端已經(jīng)定義好的功能锰镀,實(shí)現(xiàn)遠(yuǎn)程調(diào)用

CGI是這種技術(shù)的定義咖刃,而其實(shí)現(xiàn)方式多種多樣泳炉,如 Perl 是一個(gè)廣泛被用來編寫CGI程序的語言,另外嚎杨,像 Python花鹅、RubyC/C++枫浙、PHP 等也可以實(shí)現(xiàn)CGI刨肃,甚至是 Shell腳本 文件也能勝任該任務(wù);

CGI可以用任何一種語言編寫箩帚,只要這種語言具有標(biāo)準(zhǔn)輸入真友、輸出和環(huán)境變量。

在下一篇中紧帕,我們就來根據(jù)上面的流程圖來實(shí)現(xiàn)一個(gè)小型的http服務(wù)器盔然;

參考

HTTP協(xié)議入門

關(guān)于HTTP協(xié)議,一篇就夠了

HTTP/1.1 Header Field Definitions

通用網(wǎng)關(guān)接口

完是嗜!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愈案,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鹅搪,更是在濱河造成了極大的恐慌站绪,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涩嚣,死亡現(xiàn)場離奇詭異崇众,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)航厚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門顷歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幔睬,你說我怎么就攤上這事眯漩。” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵赦抖,是天一觀的道長舱卡。 經(jīng)常有香客問我,道長队萤,這世上最難降的妖魔是什么轮锥? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮要尔,結(jié)果婚禮上舍杜,老公的妹妹穿的比我還像新娘。我一直安慰自己赵辕,他們只是感情好既绩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著还惠,像睡著了一般饲握。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚕键,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天救欧,我揣著相機(jī)與錄音,去河邊找鬼嚎幸。 笑死颜矿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫉晶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼田篇,長吁一口氣:“原來是場噩夢啊……” “哼替废!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泊柬,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤椎镣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兽赁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體状答,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年刀崖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惊科。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亮钦,死狀恐怖馆截,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤蜡娶,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布混卵,位于F島的核電站,受9級特大地震影響窖张,放射性物質(zhì)發(fā)生泄漏幕随。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一宿接、第九天 我趴在偏房一處隱蔽的房頂上張望合陵。 院中可真熱鬧,春花似錦澄阳、人聲如沸拥知。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽低剔。三九已至,卻和暖如春肮塞,著一層夾襖步出監(jiān)牢的瞬間襟齿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工枕赵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猜欺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓拷窜,卻偏偏與公主長得像开皿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子篮昧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一赋荆、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,373評論 6 152
  • Http協(xié)議詳解 標(biāo)簽(空格分隔): Linux 聲明:本片文章非原創(chuàng),內(nèi)容來源于博客園作者M(jìn)IN飛翔的HTTP協(xié)...
    Sivin閱讀 5,226評論 3 82
  • 前言:最近發(fā)現(xiàn)自己在網(wǎng)絡(luò)相關(guān)這一塊基礎(chǔ)很是欠缺懊昨,所以準(zhǔn)備花時(shí)間了解一下窄潭,本文主要是講http協(xié)議的一些基礎(chǔ),和一些...
    justCode_閱讀 2,094評論 0 23
  • 深入淺出HTTP協(xié)議(WEB開發(fā)和面試必備) 1.基礎(chǔ)概念篇 a.簡介 HTTP是Hyper Text Trans...
    半世韶華憶闌珊閱讀 1,222評論 0 7
  • 本文整理自MIN飛翔博客 [1] 1. 概念 協(xié)議是指計(jì)算機(jī)通信網(wǎng)絡(luò)中兩臺計(jì)算機(jī)之間進(jìn)行通信所必須共同遵守的規(guī)定或...
    HoyaWhite閱讀 2,677評論 2 20