一篇有點長的HTTP協議詳解

一、HTTP簡介

01.什麼是HTTP

HTTP(HyperText Transfer Protocol ,超文本傳輸協議),是一個基於請求與響應的,無狀態的應用層的協議,常基於TCP/IP協議傳輸數據,互聯網上應用最廣泛的一種協議,所有的WWW文件必須遵守這個標準。

HTTP協議的設計初衷是爲了提供一種發送和接受HTML頁面的方法

02.HTTP發展史

  • HTTP/0.9版本(1991年)

特點

    • 不涉及數據包傳輸,服務器只能迴應HTML格式的字符串,不能迴應別的格式
    • 只能以GET方式請求
    • 每次請求都需要重新建立TCP連接,服務器發送完畢就關閉TCP連接
    • 沒有成爲正式的標準

請求示例

 

GET /index.html

 

響應示例

<html>
  <body>Hello World</body>
</html>

 

  • HTTP/1.0版本(1996年)

特點

    • 傳輸內容格式沒有限制
    • 增加POST、HEAD命令
    • 請求和響應的格式變了,除了數據部分,每次通訊都必須包含頭信息(HTTP Header)來描述一些元數據
    • 新增功能還包括狀態碼(status code)多字符集支持多部分發送(multi-part type)權限(authorization)緩存(cache)內容編碼(content encoding)
    • 每次請求都需要重新建立TCP連接,服務器發送完畢就關閉TCP連接
    • 正式作爲標準

請求示例

GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

響應示例

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
<body>Hello World</body>
</html>

 

  • HTTP/1.1版本(1997年)

特點

    • 增加持久連接(persistent connection),即TCP連接默認不關閉,可以被多個請求複用
    • 引入管道機制(pipelining),即在同一個TCP連接裏面,客戶端可以同時發送多個請求。這樣就進一步改進了HTTP協議的效率
    • 引入分塊傳輸編碼 (Chunked transfer encoding)機制,允許HTTP由網頁伺服器發送給客戶端應用( 通常是網頁瀏覽器)的數據可以分成多個部分
    • 引入了許多動詞方法:PUT、PATCH、OPTIONS、DELETE
    • 客戶端請求的頭信息新增了Host字段,用來指定服務器的域名

缺點:

雖然1.1版允許複用TCP連接,但是同一個TCP連接裏面,所有的數據通信是按次序進行的。服務器只有處理完一個迴應,纔會進行下一個迴應。要是前面的迴應特別慢,後面就會有許多請求排隊等着。這稱爲"隊頭堵塞"(Head-of-line blocking)。

 爲了避免這個問題,只有兩種方法:一是減少請求數,二是同時多開持久連接。這導致了很多的網頁優化技巧,比如合併腳本和樣式表、將圖片嵌入CSS代碼、域名分片(domain sharding)等等。如果HTTP協議設計得更好一些,這些額外的工作是可以避免的。

請求示例

GET /?mkt=zh-CN HTTP/1.1
Host: cn.bing.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: SRCHD=AF=NOFORM; SRCHUID=V=2&GUID=8004E55B8C8B4137BACF748D4213FE40&dmnchg=1; SRCHUSR=DOB=20191024&T=1580718980000; _EDGE_V=1; MUID=19ADA0EFC0FC60B715E2AD10C1D26108; MUIDB=19ADA0EFC0FC60B715E2AD10C1D26108; SRCHHPGUSR=CW=1536&CH=728&DPR=1.25&UTC=480&WTS=63717770478&HV=1582173694; ABDEF=MRB=1580624806993&MRNB=0; SNRHOP=I=&TS=; _EDGE_S=mkt=zh-cn&SID=32482CF6BD916165130F2280BCBF60A9; _SS=SID=32482CF6BD916165130F2280BCBF60A9&bIm=376; ipv6=hit=1582177279658&t=4
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

響應示例

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 112682
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"
Set-Cookie: SNRHOP=I=&TS=; domain=.bing.com; path=/
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-MSEdge-Ref: Ref A: A5F96665F8534BC1858A0E1C7D198764 Ref B: BJ1EDGE0106 Ref C: 2020-02-20T04:43:04Z
Set-Cookie: _EDGE_S=mkt=zh-cn&SID=32482CF6BD916165130F2280BCBF60A9; path=/; httponly; domain=bing.com
Date: Thu, 20 Feb 2020 04:43:03 GMT
Connection: close

 

  • HTTP/2版本(2015年)

特點

    • 徹底的二進制協議,頭信息和數據體都是二進制,並且統稱爲""(frame):頭信息幀和數據幀。
    • 多工(Multiplexing),複用TCP連接,在一個連接裏,客戶端和瀏覽器都可以同時發送多個請求或迴應,而且不用按照順序一一對應,這樣就避免了"隊頭堵塞"。
    • 引入數據流機制
    • 引入了頭信息壓縮機制(header compression)。
    • 允許服務器未經請求,主動向客戶端發送資源,這叫做服務器推送(server push)。

 

04.什麼是C/S架構?什麼是B/S架構?

  • C/S(Client/Sever)客戶機和服務器架構
  • B/S(Bower/Sever)瀏覽器和服務器架構

 

二、HTTP消息結構

01.統一資源定位符(URL)

URL,全稱是UniformResourceLocator, 中文叫統一資源定位符,是互聯網上用來標識某一處資源的地址。

 

協議方案名:http、ftp、mailto、file

登錄信息:如果需要網頁認證時,需要填寫該參數,所以是可選項

服務器地址:可以是IP地址形式,也可以是能被DNS服務器解析成IP地址的域名形式

端口號:指定服務器連接的端口號,選填,不填則默認爲本協議的端口號(HTTP:80,HTTPS:443)

帶層次的文件路徑:獲取資源在服務器中的具體地址

查詢字符串:針對以指定路徑的資源,可使用查詢字符串來獲取想要的參數,此項也是可選項

片段標識符:又名hash,來標記以獲取資源中的子資源(在文檔中的某個位置)

 

02.統一資源標識符 (URI)

統一資源標識符Uniform Resource Identifier)一個用於標識某一互聯網資源名稱的字符串

該種標識允許用戶對網絡中(一般指萬維網)的資源通過特定的協議進行交互操作。URI的最常見的形式是統一資源定位符(URL),經常指定爲非正式的網址。更罕見的用法是統一資源名稱(URN),其目的是通過提供一種途徑。用於在特定的命名空間資源的標識,以補充網址。

 

 

03.HTTP之請求消息Request

 1.HTTP報文格式(HTTP請求)

HTTP請求由請求行(request line)請求頭部(header)空行請求數據四個部分組成。

 

2.HTTP請求方法

HTTP/1.1協議中共定義了八種方法(有時也叫“動作”)來表明Request-URI指定的資源的不同操作方式:

OPTIONS - 返回服務器針對特定資源所支持的HTTP請求方法。也可以利用向Web服務器發送'*'的請求來測試服務器的功能性。
HEAD- 向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應消息頭中的元信息。該方法常用於測試超鏈接的有效性,是否可以訪問,以及最近是否更新。
GET - 向特定的資源發出請求。注意:GET方法不應當被用於產生“副作用”的操作中,例如在web app.中。其中一個原因是GET可能會被網絡蜘蛛等隨意訪問。
POST - 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。
PUT - 向指定資源位置上傳其最新內容。
DELETE - 請求服務器刪除Request-URI所標識的資源。
TRACE- 回顯服務器收到的請求,主要用於測試或診斷。
CONNECT - HTTP/1.1協議中預留給能夠將連接改爲管道方式的代理服務器。
PATCH - 用來將局部修改應用於某一資源,添加於規範RFC5789。

 

 3.HTTP常見的請求頭部字段名(在HTTP/1.1 協議中,所有的請求頭,除Host外,都是可選的)

  • X-Forwarded-For:用來表示HTTP請求端的真實IP,被各大HTTP代理、負載均衡等轉發服務廣泛使用

  • Cache-Control:指定請求和響應遵循的緩存機制。緩存指令是單向的(響應中出現的緩存指令在請求中未必會出現),且是獨立的(在請求消息或響應消息中設置Cache-Control並不會修改另一個消息處理過程中的緩存處理過程)。請求時的緩存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,響應消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。

Cache-Control:Public 可以被任何緩存所緩存
Cache-Control:Private 內容只緩存到私有緩存中
Cache-Control:no-cache 所有內容都不會被緩存
Cache-Control:no-store 用於防止重要的信息被無意的發佈。在請求消息中發送將使得請求和響應消息都不使用緩存。
Cache-Control:max-age 指示客戶機可以接收生存期不大於指定時間(以秒爲單位)的響應。
Cache-Control:min-fresh 指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。
Cache-Control:max-stale 指示客戶機可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那麼客戶機可以接收超出超時期指定值之內的響應消息。

  • Accept:瀏覽器端可以接受的MIME類型。例如:Accept: text/html 代表瀏覽器可以接受服務器回發的類型爲 text/html 也就是我們常說的html文檔,如果服務器無法返回text/html類型的數據,服務器應該返回一個406錯誤(non acceptable)。通配符 * 代表任意類型,例如 Accept: */* 代表瀏覽器可以處理所有類型,(一般瀏覽器發給服務器都是發這個)。

  • Accept-Encoding:瀏覽器申明自己可接收的編碼方法,通常指定壓縮方法,是否支持壓縮,支持什麼壓縮方法(gzip,deflate);Servlet能夠向支持gzip的瀏覽器返回經gzip編碼的HTML頁面。許多情形下這可以減少5到10倍的下載時間。例如: Accept-Encoding: gzip, deflate。如果請求消息中沒有設置這個域,服務器假定客戶端對各種內容編碼都可以接受。

  • Accept-Language:瀏覽器申明自己接收的語言。語言跟字符集的區別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等;例如:Accept-Language: en-us。如果請求消息中沒有設置這個報頭域,服務器假定客戶端對各種語言都可以接受。

  • Accept-Charset:瀏覽器可接受的字符集。如果在請求消息中沒有設置這個域,缺省表示任何字符集都可以接受。

  • User-Agent:告訴HTTP服務器,客戶端使用的操作系統和瀏覽器的名稱和版本。例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)。

  • Content-Type:例如:Content-Type: application/x-www-form-urlencoded。

  • Referer:包含一個URL,用戶從該URL代表的頁面出發訪問當前請求的頁面。提供了Request的上下文信息的服務器,告訴服務器我是從哪個鏈接過來的,比如從我主頁上鍊接到一個朋友那裏,他的服務器就能夠從HTTP Referer中統計出每天有多少用戶點擊我主頁上的鏈接訪問他的網站。例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT

  • Connection:例如:Connection: keep-alive 當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經建立的連接。HTTP 1.1默認進行持久連接。利用持久連接的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點,Servlet需要在應答中發送一個Content-Length頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,然後在正式寫出內容之前計算它的大小。Connection: close 代表一個Request完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP連接會關閉,當客戶端再次發送Request,需要重新建立TCP連接。

  • Host:(發送請求時,該頭域是必需的)主要用於指定被請求資源的Internet主機和端口號,它通常從HTTP URL中提取出來的。HTTP/1.1請求必須包含主機頭域,否則系統會以400狀態碼返回。例如: 我們在瀏覽器中輸入:http://www.guet.edu.cn/index.html,瀏覽器發送的請求消息中,就會包含Host請求頭域:Host:http://www.guet.edu.cn,此處使用缺省端口號80,若指定了端口號,則變成:Host:指定端口號。

  • Cookie:最重要的請求頭之一, 將cookie的值發送給HTTP服務器。

  • Content-Length:表示請求消息正文的長度。例如:Content-Length: 38。

  • Authorization:授權信息,通常出現在對服務器發送的WWW-Authenticate頭的應答中。主要用於證明客戶端有權查看某個資源。當瀏覽器訪問一個頁面時,如果收到服務器的響應代碼爲401(未授權),可以發送一個包含Authorization請求報頭域的請求,要求服務器對其進行驗證。

  • From:請求發送者的email地址,由一些特殊的Web客戶程序使用,瀏覽器不會用到它。

  • Range:可以請求實體的一個或者多個子範圍。例如,

  •  

     

    04.HTTP之響應消息Response

    1.HTTP報文格式(HTTP響應)

     

    • 狀態行由三部分組成,分別爲:協議版本狀態碼狀態碼描述,之間由空格間隔
    • 響應頭部與請求頭部類似,也包含了很多有用信息
    • 空行,這一行非常重要,表示響應頭的結束
    • 響應正文,服務器返回的文檔,最常見的爲HTML網頁

     

    2.HTTP常見的狀態碼

    狀態代碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別:

    1xx:指示信息--表示請求已接收,繼續處理

    2xx:成功--表示請求已被成功接收、理解、接受

    3xx:重定向--要完成請求必須進行更進一步的操作

    4xx:客戶端錯誤--請求有語法錯誤或請求無法實現

    5xx:服務器端錯誤--服務器未能實現合法的請求

    200 OK                        //客戶端請求成功
    400 Bad Request               //客戶端請求有語法錯誤,不能被服務器所理解
    401 Unauthorized              //請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用 
    403 Forbidden                 //服務器收到請求,但是拒絕提供服務
    404 Not Found                 //請求資源不存在,eg:輸入了錯誤的URL
    500 Internal Server Error     //服務器發生不可預期的錯誤
    503 Server Unavailable        //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常

     

    3.HTTP常見響應頭部字段名

    • Allow:服務器支持哪些請求方法(如GET、POST等)

  • Date:表示消息發送的時間,時間的描述格式由rfc822定義。

  • Expires:指明應該在什麼時候認爲文檔已經過期,從而不再緩存它,重新從服務器獲取,會更新緩存。過期之前使用本地緩存。HTTP1.1的客戶端和緩存會將非法的日期格式(包括0)看作已經過期。

  • P3P:用於跨域設置Cookie, 這樣可以解決iframe跨域訪問cookie的問題 

  • Set-Cookie:非常重要的header, 用於把cookie發送到客戶端瀏覽器,每一個寫入cookie都會生成一個Set-Cookie。

    • ETag:和If-None-Match 配合使用。

  • Last-Modified:用於指示資源的最後修改日期和時間。Last-Modified也可用setDateHeader方法來設置。

  • Content-Type:WEB服務器告訴瀏覽器自己響應的對象的類型和字符集。Servlet默認爲text/plain,但通常需要顯式地指定爲text/html。由於經常要設置Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。可在web.xml文件中配置擴展名和MIME類型的對應關係。

    • Content-Range:用於指定整個實體中的一部分的插入位置,他也指示了整個實體的長度。在服務器向客戶返回一個部分響應,它必須描述響應覆蓋的範圍和整個實體長度。一般格式:Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-length。

  • Content-Length:指明實體正文的長度,以字節方式存儲的十進制數字來表示。在數據下行的過程中,Content-Length的方式要預先在服務器中緩存所有數據,然後所有數據再一股腦兒地發給客戶端。只有當瀏覽器使用持久HTTP連接時才需要這個數據。如果你想要利用持久連接的優勢,可以把輸出文檔寫入ByteArrayOutputStram,完成後查看其大小,然後把該值放入Content-Length頭,最後通過byteArrayStream.writeTo(response.getOutputStream()發送內容。

  • Content-Encoding:WEB服務器表明自己使用了什麼壓縮方法(gzip,deflate)壓縮響應中的對象。只有在解碼之後纔可以得到Content-Type頭指定的內容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet應該通過查看Accept-Encoding頭(即request.getHeader("Accept-Encoding"))檢查瀏覽器是否支持gzip,爲支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,爲其他瀏覽器返回普通頁面。

  • Content-Language:WEB服務器告訴瀏覽器自己響應的對象所用的自然語言。沒有設置該域則認爲實體內容將提供給所有的語言閱讀。

  • Server:指明HTTP服務器用來處理請求的軟件信息。。

  • X-AspNet-Version:如果網站是用ASP.NET開發的,這個header用來表示ASP.NET的版本。

  • X-Powered-By:表示網站是用什麼技術開發的。

  • Connection:例如:Connection: keep-alive 當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經建立的連接。Connection: close 代表一個Request完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP連接會關閉,當客戶端再次發送Request,需要重新建立TCP連接。

  • Location:用於重定向一個新的位置,包含新的URL地址。表示客戶應當到哪裏去提取文檔。Location通常不是直接設置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼爲302。Location響應報頭域常用在更換域名的時候。

  • Refresh:表示瀏覽器應該在多少時間之後刷新文檔,以秒計。除了刷新當前文檔之外,你還可以通過setHeader("Refresh", "5; URL=http://host/path")讓瀏覽器讀取指定的頁面。注意這種功能通常是通過設置HTML頁面HEAD區的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">實現,這是因爲,自動刷新或重定向對於那些不能使用CGI或Servlet的HTML編寫者十分重要。但是,對於Servlet來說,直接設置Refresh頭更加方便。注意Refresh的意義是“N秒之後刷新本頁面或訪問指定頁面”,而不是“每隔N秒刷新本頁面或訪問指定頁面”。因此,連續刷新要求每次都發送一個Refresh頭,而發送204狀態代碼則可以阻止瀏覽器繼續刷新,不管是使用Refresh頭還是<META HTTP-EQUIV="Refresh" ...>。注意Refresh頭不屬於HTTP 1.1正式規範的一部分,而是一個擴展,但Netscape和IE都支持它。

  • 三、HTTP工作原理

    • A.客戶端通過TCP三次握手與服務器建立連接

  • B.TCP建立連接成功後,向服務器發送HTTP請求

  • C.服務器接收到HTTP請求後,向客戶端發送HTTP響應

  • D.客戶端通過TCP四次斷開,與服務器斷開TCP連接

  •  

     

     

    四、引用鏈接

  • HTTP 協議入門

  • HTTP, by Wikipedia

  • 《圖解HTTP》

  • 未完,待續。。。。。。

    更多精彩文章請關注公衆號 白帽技術與網絡安全

    ps:關注公衆號還可以領取海量學習視頻呦~

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章