1. 程式人生 > >前端01.http協議回顧

前端01.http協議回顧

http

一、http1.0和1.1之間有什麽區別?

http1.0 :每一次請求/響應都會建立並關閉一次連接,相應速度慢。

http1.1:在同一個tcp連接中,可以傳輸多個響應或請求。http1.1默認還開啟長連接。

二、客戶端請求。

GET / HTTP/1.1 #動作和http協議的版本號

Host: www.test.com:8088 #客戶端訪問的主機地址

Connection: keep-alive #長連接

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 #當前瀏覽器所能解析的數據類型

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 #客戶端的操作系統以及瀏覽器等信息。

Accept-Encoding: gzip, deflate, sdch #瀏覽器用來告訴服務器,自己支持的編碼類型。

Accept-Language: zh-CN,zh;q=0.8 #瀏覽器當前的語言信息。

客戶端請求頭,大概分為四部分:

請求首行; #請求方式 請求路徑 協議和版本,例如:GET /index.html HTTP/1.1

請求頭信息;# 請求頭名稱:請求頭內容,即為key:value格式,例如:Host:localhost

空行; #用來與請求體分隔開

請求體。 # GET沒有請求體,只有POST有請求體。

GET請求

特點

http默認的請求方式為get。

get請求沒有任何請求體。

一個get請求,大小一定在1k之內。

get請求的內容,會暴露在地址欄中。

產生get請求的操作:

在瀏覽器地址欄中輸入一個URL,這一定會是個get請求。

點擊頁面上的一個連接,也會是一個get請求。

提交表單,默認情況下是get,可以設置為post。

下面是一個瀏覽器去訪問百度搜索時,產生的請求頭信息:

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

#瀏覽器用來告訴服務器,自己這裏可以解析的文檔類型,其實這裏包含了*/*,就表示什麽都可以接收。

Accept-Encoding:gzip, deflate, sdch

#支持的壓縮格式。數據在網絡上傳遞時,可能服務器會把數據壓縮後再發送

Accept-Language:zh-CN,zh;q=0.8

#當前客戶端支持的語言,可以在瀏覽器的工具選項中找到語言相關信息

Cache-Control:max-age=0

Connection:keep-alive

#瀏覽器告訴服務端支持長鏈接的方式,保持一段時間鏈接,默認為3000ms

Cookie:BAIDUID=7AD83D51481D0BE4DB3250B5273A7A01:FG=1; BIDUPSID=7AD83D51481D0BE4DB3250B5273A7A01; PSTM=1483207633; BCLID=599596736169088288;

#因為不是第一次訪問這個地址,所以會在請求中把上一次服務器響應中發送過來的Cookie在請求中一並發送去過;這個Cookie的名字為BAIDUUID,FG,BIDUPSID.PSTM,BCLID。

#如果對cookie不理解的話,可以先把cookie當成一個字典,這個字典裏可以放多組鍵值對,

BDSFRCVID=B9_sJeCGQG04CSbZK5LXuyRgDeKKnW7TH6aP2rQCi3AO4CkVJ2uIEG0Ptf8g0KubaKiaogKK0gOTH65P; H_BDCLCKID_SF=tJAD_CtatD-3ejrnhCTVMt_e2x7-2D62aKDssR3n-hcqEp3hQT0MLptVW44tWtntMGrMKn5cWbrRMUbSj4QmDRDuLUue3x4J0K3paDoaWl5nhMJmb67JDMP0-xQia4oy523ion3vQpP-MftuD6-ajjO0DG8sKC62atoLBRjOMJnqD6rnhPF3QJT3KP6-3MbI3b4J5MOtyqkh8hRG2q5JQ-LUyUTUth37JD6Totol0bI5EqAmLPR4y6D0ytoxJpOJ5JbMopvaKJjvjJjvbURvD--g3-Aqtl8EtJAD_CtatD-3ejrnhCTVMt_e2x7-2D62aKDs5DT7-hcqEp3hQT0MLptVW44tWpvtMGrMKn5cWbrRMUbSj4QmDRDuLUue3x4J0K3paDoaWl5nhMJmb67JDMP0-xQia4oy523ion3vQpP-Mftu-n5jHjJ0DNt83e; BD_CK_SAM=1; PSINO=1; BD_UPN=123253; H_PS_645EC=c485lXcS%2F7FBtERrH33%2FHldUI6NyBW8PijQ%2F%2F54A4h75m4RucmVSSJDxXBg; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDSVRTM=0; BD_HOME=0; H_PS_PSSID=1454_21081_21673_20930; __bsi=12503378464846675469_00_815_R_N_6_0303_C02F_N_I_I_0

Host:www.baidu.com

Upgrade-Insecure-Requests:1

User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36

Referer:http://www.baidu.com

#註意!!referer這個標記,只有在通過其他url上連接過來之後,才會產生,請求來自哪個頁面,例如你在百度上點擊鏈接到了這裏,那麽Referer:http://www.baidu.com;如果你是在瀏覽器的地址欄中直接輸入的地址,那麽就沒有Referer這個請求頭了。

2.post請求。

特點:

請求的數據不會出現在地址欄中。(提交給服務端的參數,都會被放進請求體。)

數據的大小無上限。

有請求體。

當遇到中文會使用url編碼。

在這解釋下什麽是url編碼。

我們都知道Http協議中參數的傳輸是"key=value"這種簡直對形式的,如果要傳多個參數就需要用“&”符號對鍵值對進行分割。如"?name1=value1&name2=value2",這樣在服務端在收到這種字符串的時候,會用“&”分割出每一個參數,然後再用“=”來分割出參數值。

針對“name1=value1&name2=value2”我們來說一下客戶端到服務端的概念上解析過程:

上述字符串在計算機中用ASCII嗎表示為:

6E616D6531 3D 76616C756531 26 6E616D6532 3D 76616C756532。

6E616D6531:name1

3D:=

76616C756531:value1

26:&

6E616D6532:name2

3D:=

76616C756532:value2

服務端在接收到該數據後就可以遍歷該字節流,首先一個字節一個字節的吃,當吃到3D這字節後,服務端就知道前面吃得字節表示一個key,再想後吃,如果遇到26,說明從剛才吃的3D到26子節之間的是上一個key的value,以此類推就可以解析出客戶端傳過來的參數。

現在有這樣一個問題,如果我的參數值中就包含=或&這種特殊字符的時候該怎麽辦。

比如說“name1=value1”,其中value1的值是“va&lu=e1”字符串,那麽實際在傳輸過程中就會變成這樣“name1=va&lu=e1”。我們的本意是就只有一個鍵值對,但是服務端會解析成兩個鍵值對,這樣就產生了奇異。

如何解決上述問題帶來的歧義呢?解決的辦法就是對參數進行URL編碼

URL編碼只是簡單的在特殊字符的各個字節前加上%,例如,我們對上述會產生奇異的字符進行URL編碼後結果:“name1=va%26lu%3D”,這樣服務端會把緊跟在“%”後的字節當成普通的字節,就是不會把它當成各個參數或鍵值對的分隔符。

說道了post請求,在補充兩個請求頭的標記:

Content-Type: application/x-www-form-urlencoded:表單的數據類型,說明會使用url格式編碼數據;url編碼的數據都是以“%”為前綴,後面跟隨兩位的16進制。

Content-Length:13:請求體的長度,這裏表示13個字節。

三、服務端響應頭。

服務器回復給客戶端的響應報頭大概分為3部分。

響應頭信息,空行,響應體。

Request URL:http://127.0.0.1:8090/login/

#客戶端請求的url

Request Method:GET

#客戶端請求的動作

Status Code:200 OK

#返回給客戶端的狀態碼

Remote Address:127.0.0.1:8090

Response Headers

view source

Content-Type:text/html; charset=utf-8

#服務端當前應答給客戶端的數據類型是什麽,以及字符編碼

Date:Wed, 26 Oct 2016 06:48:50 GMT

#響應時間

Server:WSGIServer/0.2 CPython/3.5.2

#服務端類型

X-Frame-Options:SAMEORIGIN

#響應體

Request URL:http://127.0.0.1:8090/login/

Request Method:GET

Status Code:200 OK

Remote Address:127.0.0.1:8090

Response Headers

view source

Content-Type:text/html; charset=utf-8

Date:Wed, 26 Oct 2016 06:48:50 GMT

Server:WSGIServer/0.2 CPython/3.5.2

X-Frame-Options:SAMEORIGIN

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

</head>

<body>

<form action="/login/" method="post">

用戶名:<input type="text" name="username"/>

<input type="submit" value="提交"/>

</form>

</body>

</html>


HTTP/1.1 200 OK:響應協議為HTTP1.1,狀態碼為200,表示請求成功,OK是對狀態碼的解釋;

Server:WSGIServer/0.2 CPython/3.5.2:服務器的版本信息;

Content-Type: text/html;charset=UTF-8:響應體使用的編碼為UTF-8;

Content-Length: 724:響應體為724字節;

Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/hello:響應給客戶端的Cookie;

Date: Wed, 25 Sep 2012 04:15:03 GMT:響應的時間,這可能會有8小時的時區差

關於狀態碼做一個小的補充:

200,403,404,50x 這些狀態碼太常見了,在這裏不做過多說明,主要說下302和304。

302:地址跳轉,重定向,當響應碼為302時,表示服務器要求瀏覽器重新再發一個請求,服務器會發送一個響應頭Location,它指定了新請求的URL地址。

304:假如說,用戶第一次通過瀏覽器向服務器請求一個資源文件比如說一個html文件。

服務器在應答的時候,會加一個Last-Modified的響應頭,這個響應頭說明了這個html文件最後的修改時間,瀏覽器會把這個html文件的內容,以及最後的響應時間記錄下來。

當用戶第二次請求這個html文件時,在請求頭中,會包含一個IF-Modified-since的請求頭,這個請求頭對應的值就是,第一次向服務器發起請求時,服務器通過Last-Modified響應頭發給客戶端的值,也就是瀏覽器要請求的這個資源文件的最後修改時間。

If-Modified-Since請求頭就是在告訴服務器,我這裏瀏覽器緩存的這個文件最後修改時間是否和服務器端這個文件的最後的修改時間相等,如果相等,那麽服務端直接就返回304就不用再響應這個文件的內容,瀏覽器會把緩存的內容直接顯示出來。

而服務器端會獲取If-Modified-Since值,與瀏覽器緩存的文件當前最後修改時間比對,如果相同,服務器會發響應碼304,表示index.html與瀏覽器上次緩存的相同,無需再次發送,瀏覽器可以顯示自己的緩存頁面,如果比對不同,那麽說明index.html已經做了修改,服務器會響應200。

下面是圖解:

四、關於http協議的一些誤區糾正。

http這種協議是一種無狀態協議,沒有任何記憶能力,瀏覽器一旦打開了服務器發來的網頁,那麽瀏覽器和服務器之間就沒有任何聯系了。

其實很多網上商城的購物車功能,都需要借助於Cookie或Session或服務器端API記錄這些信息,請求服務器結算頁面時同時將這些信息提交到服務器。

當你登錄到一個網站時,你的登錄狀態也是由Cookie或Session來“記憶”的,因為服務器並不知道你是否登錄。

說道這裏,可能有人會問,既然http是無狀態協議,那麽保持的長連接是個什麽鬼?

用一句話來說就是,無狀態不代表HTTP不能保持TCP連接!

從HTTP/1.1起,默認都開啟了Keep-Alive,保持連接特性,簡單地說,當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經建立的連接。

keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務器軟件(如Apache)中設定這個時間。

五、其他一些常見的響應頭補充。

這些頭都會導致瀏覽器不緩存。

Expires: -1;

Cache-Control: no-cache;

Pragma: no-cache;

具有刷新的功能,3秒後自動跳轉到http://www.baidu.com。

#Refresh#: 時間;url=http://www.baidu.com

這些響應頭在html中都是可以自定義的!!

在HTMl頁面中可以使用來指定響應頭,例如在index.html頁面中給出,表示瀏覽器只會顯示index.html頁面3秒,然後自動跳轉到http://www.baidu.com.


本文出自 “reBiRTH” 博客,請務必保留此出處http://suhaozhi.blog.51cto.com/7272298/1928820

前端01.http協議回顧