天天看點

前端01.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 

   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/

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

      本文轉自蘇浩智 51CTO部落格,原文連結:http://blog.51cto.com/suhaozhi/1928820,如需轉載請自行聯系原作者