一 HTTP概述
HTTP(hypertext transport protocol), 即超文本傳輸協議.這個協議詳細規定了瀏覽器和萬維網服務器之間互相通信的規則.
HTTP就是一個通信規則,通信規則規定了客戶端發送給服務器的內容格式,也規定了服務器發送給客戶端的內容格式.其實我們要學習的就是這兩個格式!客戶端發給服務器的格式叫“請求協議”;服務器發給客戶端的格式叫"響應協議"。
特點:
- HTTP叫超文本傳輸協議,基於請求/響應模式的!
- HTTP是無狀態協議。
URL:統一資源定位符,就是一個網址:協議名://域名:端口/路徑,例如:http://www.oldboy.cn:80/index.html
二 解讀web服務本質
1.cs模式 client------server
基於TCP協議 (UDP協議)
socket與TCP協議的關系-----socket是對TCP協議,UDP協議的封裝
*web服務就是一種標准的cs模式--------bs模式(browser和server)
GET /favicon.ico HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 Accept: */* Referer: http://127.0.0.1:8080/ Accept-Encoding: gzip, deflate, sdch, br Accept-Language: zh-CN,zh;q=0.8 Cookie: sessionid=e0ci3j4mwkg8itrtr5so824raj8wilfk; csrftoken=0nNXMorXRmbll9pDD1mEWAlUmqPLPDOMvY5zQvRawcbXyuiuSaYtTGkzQUB5XfPF
Http協議:
一 請求協議 (瀏覽器------>server)
url: www.baidu.com?a=1
(1)請求首行 GET /favicon.ico HTTP/1.1
(2)請求頭信息
Host: 127.0.0.1:8080 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 Accept: text/html Accept-Encoding: gzip, deflate, sdch, br Accept-Language: zh-CN,zh;q=0.8 Referer: http://127.0.0.1:8080/ Cookie: sessionid=e0ci3j4mwkg8itrtr5so824raj8wilfk; csrftoken=0nNXMorXRmbll9pDD1mEWAlUmqPLPDOMvY5zQvRawcbXyuiuSaYtTGkzQUB5XfPF
(3) 空行
(4)請求體(請求數據)----------------get請求體不存在
二 響應協議(server-----------》瀏覽器)
響應首行; HTTP/1.1 200 OK
響應頭信息;
空行;
響應體。
三 請求協議
請求協議的格式如下:
請求首行; // 請求方式 請求路徑 協議和版本,例如:GET /index.html HTTP/1.1 請求頭信息;// 請求頭名稱:請求頭內容,即為key:value格式,例如:Host:localhost 空行; // 用來與請求體分隔開 請求體。 // GET沒有請求體,只有POST有請求體。
瀏覽器發送給服務器的內容就這個格式的,如果不是這個格式服務器將無法解讀!在HTTP協議中,請求有很多請求方法,其中最為常用的就是GET和POST。不同的請求方法之間的區別,后面會一點一點的介紹。
3.1 GET請求
HTTP默認的請求方法就是GET
* 沒有請求體
* 數據必須在1K之內!
* GET請求數據會暴露在瀏覽器的地址欄中
GET請求常用的操作:
1. 在瀏覽器的地址欄中直接給出URL,那么就一定是GET請求
2. 點擊頁面上的超鏈接也一定是GET請求
3. 提交表單時,表單默認使用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:no-cache Connection:keep-alive Cookie:csrftoken=z5H43ZwARx7AIJ82OEizBOWbsAQA2LPk Host:127.0.0.1:8090 Pragma:no-cache Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36 Name login/ requests ❘ 737 B transferred ❘ Finish: 5 ms ❘ DOMContentLoaded: 14 ms ❘ Load: 14 ms
- GET 127.0.0.1:8090/login HTTP/1.1:GET請求,請求服務器路徑為 127.0.0.1:8090/login ,協議為1.1;
- Host:localhost:請求的主機名為localhost;
- *User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0:與瀏覽器和OS相關的信息。有些網站會顯示用戶的系統版本和瀏覽器版本信息,這都是通過獲取User-Agent頭信息而來的;
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8:告訴服務器,當前客戶端可以接收的文檔類型,其實這里包含了*/*,就表示什么都可以接收;
- Accept-Language: zh-cn,zh;q=0.5:當前客戶端支持的語言,可以在瀏覽器的工具選項中找到語言相關信息;
- Accept-Encoding: gzip, deflate:支持的壓縮格式。數據在網絡上傳遞時,可能服務器會把數據壓縮后再發送;
- Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7:客戶端支持的編碼;
- Connection: keep-alive:客戶端支持的鏈接方式,保持一段時間鏈接,默認為3000ms;
- Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98:因為不是第一次訪問這個地址,所以會在請求中把上一次服務器響應中發送過來的Cookie在請求中一並發送去過;這個Cookie的名字為JSESSIONID

HTTP無狀態:無狀態是指協議對於事務處理沒有記憶能力,服務器不知道客戶端是什么狀態。從另一方面講,打開一個服務器上的網頁 和你之前打開這個服務器上的網頁之間沒有任何聯系 如果你要實現一個購物車,需要借助於Cookie或Session或服務器端API(如NSAPI and ISAPI)記錄這些信息,請求服務器結算頁面時同時將這些信息提交到服務器 當你登錄到一個網站時,你的登錄狀態也是由Cookie或Session來“記憶”的,因為服務器並不知道你是否登錄 優點:服務器不用為每個客戶端連接分配內存來記憶大量狀態,也不用在客戶端失去連接時去清理內存,以更高效地去處理WEB業務 缺點:客戶端的每次請求都需要攜帶相應參數,服務器需要處理這些參數 容易犯的誤區: 1、HTTP是一個無狀態的面向連接的協議,無狀態不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協議(無連接) 2、從HTTP/1.1起,默認都開啟了Keep-Alive,保持連接特性,簡單地說,當一個網頁打開完成后,客戶端和服務器之間用於傳輸 HTTP數據的TCP連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經建立的連接 3、Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務器軟件(如Apache)中設定這個時間
3.2 POST請求
(1). 數據不會出現在地址欄中
(2). 數據的大小沒有上限
(3). 有請求體
(4). 請求體中如果存在中文,會使用URL編碼!
username=%E5%BC%A0%E4%B8%89&password=123

我們都知道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請求,但表單默認是GET
<form action="" method="post"> 關鍵字:<input type="text" name="keyword"/> <input type="submit" value="提交"/> </form>
輸入請求信息后點擊提交,查看請求內容如下:
Request Headers Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip, deflate Accept-Language:zh-CN,zh;q=0.8 Cache-Control:no-cache Connection:keep-alive Content-Length:13 Content-Type:application/x-www-form-urlencoded Cookie:csrftoken=z5H43ZwARx7AIJ82OEizBOWbsAQA2LPk Host:127.0.0.1:8090 Origin:http://127.0.0.1:8090 Pragma:no-cache Referer:http://127.0.0.1:8090/login/ Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36 Form Data username:yuan
POST請求是可以有體的,而GET請求不能有請求體。
- Referer: http://localhost:8080/hello/index.jsp:請求來自哪個頁面,例如你在百度上點擊鏈接到了這里,那么Referer:http://www.baidu.com;如果你是在瀏覽器的地址欄中直接輸入的地址,那么就沒有Referer這個請求頭了;
- Content-Type: application/x-www-form-urlencoded:表單的數據類型,說明會使用url格式編碼數據;url編碼的數據都是以“%”為前綴,后面跟隨兩位的16進制。
- Content-Length:13:請求體的長度,這里表示13個字節。
- keyword=hello:請求體內容!hello是在表單中輸入的數據,keyword是表單字段的名字

Referer請求頭是比較有用的一個請求頭,它可以用來做統計工作,也可以用來做防盜鏈。
統計工作:我公司網站在百度上做了廣告,但不知道在百度上做廣告對我們網站的訪問量是否有影響,那么可以對每個請求中的Referer進行分析,如果Referer為百度的很多,那么說明用戶都是通過百度找到我們公司網站的。
防盜鏈:我公司網站上有一個下載鏈接,而其他網站盜鏈了這個地址,例如在我網站上的index.html頁面中有一個鏈接,點擊即可下載JDK7.0,但有某個人的微博中盜鏈了這個資源,它也有一個鏈接指向我們網站的JDK7.0,也就是說登錄它的微博,點擊鏈接就可以從我網站上下載JDK7.0,這導致我們網站的廣告沒有看,但下載的卻是我網站的資源。這時可以使用Referer進行防盜鏈,在資源被下載之前,我們對Referer進行判斷,如果請求來自本網站,那么允許下載,如果非本網站,先跳轉到本網站看廣告,然后再允許下載。
四 響應協議
4.1 響應內容
響應協議格式如下:
響應首行;
響應頭信息;
空行;
響應體。
響應內容是由服務器發送給瀏覽器的內容,瀏覽器會根據響應內容來顯示。遇到<img src=''>會開一個新的線程加載,所以有時圖片多的話,內容會先顯示出來,然后圖片才一張張加載出來。
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小時的時區差;
4.2 狀態碼
響應頭對瀏覽器來說很重要,它說明了響應的真正含義。例如200表示響應成功了,302表示重定向,這說明瀏覽器需要再發一個新的請求。
- 200:請求成功,瀏覽器會把響應體內容(通常是html)顯示在瀏覽器中;
- 404:(客戶端問題)請求的資源沒有找到,說明客戶端錯誤的請求了不存在的資源;
- 500:(服務端問題)請求資源找到了,但服務器內部出現了錯誤;
- 302:(網站搬家了,跳轉)重定向,當響應碼為302時,表示服務器要求瀏覽器重新再發一個請求,服務器會發送一個響應頭Location,它指定了新請求的URL地址;
- 304:
當用戶第一次請求index.html時,服務器會添加一個名為Last-Modified響應頭,這個頭說明了 index.html的最后修改時間,瀏覽器會把index.html內容,以及最后響應時間緩存下來。當用戶第 二次請求index.html時,在請求中包含一個名為If-Modified-Since請求頭,它的值就是第一次請 求時服務器通過Last-Modified響應頭發送給瀏覽器的值,即index.html最后的修改時間, If-Modified-Since請求頭就是在告訴服務器,我這里瀏覽器緩存的index.html最后修改時間是這個, 您看看現在的index.html最后修改時間是不是這個,如果還是,那么您就不用再響應這個index.html 內容了,我會把緩存的內容直接顯示出來。而服務器端會獲取If-Modified-Since值,與index.html 的當前最后修改時間比對,如果相同,服務器會發響應碼304,表示index.html與瀏覽器上次緩存的相 同,無需再次發送,瀏覽器可以顯示自己的緩存頁面,如果比對不同,那么說明index.html已經做了修 改,服務器會響應200。
4.3 其他響應頭
告訴瀏覽器不要緩存的響應頭:
- Expires: -1;
- Cache-Control: no-cache;
- Pragma: no-cache;
自動刷新響應頭,瀏覽器會在3秒之后請求http://www.baidu.com:
- Refresh: 3;url=http://www.baidu.com
4.4 HTML中指定響應頭
在HTMl頁面中可以使用<meta http-equiv="" content="">來指定響應頭,例如在index.html頁面中給出<meta http-equiv="Refresh" content="3;url=http://www.baidu.com">,表示瀏覽器只會顯示index.html頁面3秒,然后自動跳轉到http://www.baidu.com.