HTTP協(xié)議的認(rèn)識

HTTP的地址格式如下:

http_URL = "http:" "http://" host [ ":" port ] [ abs_path [ "?" query ]]
協(xié)議和host不分大小寫
HTTP消息

一個HTTP消息可能是request或者response消息,兩種類型的消息都是由開始行(start-line),零個或多個header域,一個表示header域結(jié)束的空行(也就是,一個以CRLF為前綴的空行),一個可能為空的消息主體(message-body)。一個合格的HTTP客戶端不應(yīng)該在消息頭或者尾添加多余的CRLF,服務(wù)端也會忽略這些字符。

header的值不包括任何前導(dǎo)或后續(xù)的LWS(線性空白),線性空白可能會出現(xiàn)在域值(filed-value)的第一個非空白字符之前或最后一個非空白字符之后。前導(dǎo)或后續(xù)的LWS可能會被移除而不會改變域值的語意。任何出現(xiàn)在filed-content之間的LWS可能會被一個SP(空格)代替。header域的順序不重要,但建議把常用的header放在前邊(協(xié)議里這么說的)。

Request消息

RFC2616中這樣定義HTTP Request 消息:

Request = Request-Line
          *(( general-header 
            | request-header(跟本次請求相關(guān)的一些header)
            | entity-header ) CRLF)(跟本次請求相關(guān)的一些header)
          CRLF
          [ message-body ]

一個HTTP的request消息以一個請求行開始,從第二行開始是header,接下來是一個空行,表示header結(jié)束,最后是消息體。

請求行的定義如下:

//請求行的定義
Request-Line = Method SP Request-URL SP HTTP-Version CRLF

//方法的定義
Method = "OPTIONS" | "GET" | "HEAD"  |"POST" |"PUT" |"DELETE" |"TRACE" |"CONNECT"  | extension-method

//資源地址的定義
Request-URI   ="*" | absoluteURI | abs_path | authotity(CONNECT)

Request消息中使用的header可以是general-header或者request-header,request-header(后邊會講解)。其中有一個比較特殊的就是Host,Host會與reuqest Uri一起來作為Request消息的接收者判斷請求資源的條件,方法如下:

1 、 如果Request-URI是絕對地址(absoluteURI),這時請求里的主機(jī)存在于Request-URI里。任何出現(xiàn)在請求里Host頭域值應(yīng)當(dāng)被忽略。
2 、 假如Request-URI不是絕對地址(absoluteURI),并且請求包括一個Host頭域,則主機(jī)由該Host頭域值決定。
3 、假如由規(guī)則1或規(guī)則2定義的主機(jī)是一個無效的主機(jī),則應(yīng)當(dāng)以一個400(錯誤請求)錯誤消息返回。

Response消息

響應(yīng)消息跟請求消息幾乎一模一樣,定義如下:

   Response      = Status-Line              
                   *(( general-header        
                    | response-header       
                    | entity-header ) CRLF)  
                   CRLF
                   [ message-body ]

可以看到,除了header不使用request-header之外,只有第一行不同,響應(yīng)消息的第一行是狀態(tài)行,其中就包含大名鼎鼎的返回碼
Status-Line的內(nèi)容首先是協(xié)議的版本號,然后跟著返回碼,最后是解釋的內(nèi)容,它們之間各有一個空格分隔,行的末尾以一個回車換行符作為結(jié)束。定義如下:

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
返回碼

返回碼是一個3位數(shù),第一位定義的返回碼的類別,總共有5個類別,它們是:

  - 1xx: Informational - Request received, continuing process
  - 2xx: Success - The action was successfully received,
    understood, and accepted
  - 3xx: Redirection - Further action must be taken in order to  complete the request
  - 4xx: Client Error - The request contains bad syntax or cannot
    be fulfilled
  - 5xx: Server Error - The server failed to fulfill an apparently  valid request

RFC2616中接著又給出了一系列返回碼的擴(kuò)展,這些都是我們平時會用到的,但是那些只是示例,HTTP1.1不強(qiáng)制通信各方遵守這些擴(kuò)展的返回碼,通信各方在返回碼的實現(xiàn)上只需要遵守以上邊定義的這5種類別的定義,意思就是,返回碼的第一位要嚴(yán)格按照文檔中所述的來,其他的隨便定義。
任何人接收到一個不認(rèn)識的返回碼xyz,都可以把它當(dāng)做x00來對待。對于不認(rèn)識的返回碼的響應(yīng)消息,不可以緩存。

Header

RFC2616中定義了4種header類型,在通信各方都認(rèn)可的情況下,請求頭可以被擴(kuò)展的(可信的擴(kuò)展只能等到協(xié)議的版本更新),如果接收者收到了一個不認(rèn)識的請求頭,這個頭將會被當(dāng)做實體頭。4種頭類型如下:

  1. 通用頭(General Header Fields):可用于request,也可用于response的頭,但不可作為實體頭,只能作為消息的頭。
general-header = Cache-Control            ; Section 14.9
              | Connection               ; Section 14.10
              | Date                     ; Section 14.18
              | Pragma                   ; Section 14.32
              | Trailer                  ; Section 14.40
              | Transfer-Encoding        ; Section 14.41
              | Upgrade                  ; Section 14.42
              | Via                      ; Section 14.45
              | Warning                  ; Section 14.46
  1. 請求頭(Request Header Fields):被請求發(fā)起端用來改變請求行為的頭。
request-header = Accept                   ; Section 14.1
               | Accept-Charset           ; Section 14.2
               | Accept-Encoding          ; Section 14.3
               | Accept-Language          ; Section 14.4
               | Authorization            ; Section 14.8
               | Expect                   ; Section 14.20
               | From                     ; Section 14.22
               | Host                     ; Section 14.23
               | If-Match                 ; Section 14.24
               | If-Modified-Since        ; Section 14.25
               | If-None-Match            ; Section 14.26
               | If-Range                 ; Section 14.27
               | If-Unmodified-Since      ; Section 14.28
               | Max-Forwards             ; Section 14.31
               | Proxy-Authorization      ; Section 14.34
               | Range                    ; Section 14.35
               | Referer                  ; Section 14.36
               | TE                       ; Section 14.39
               | User-Agent               ; Section 14.43
  1. 響應(yīng)頭(Response Header Fields):被服務(wù)器用來對資源進(jìn)行進(jìn)一步的說明。
response-header = Accept-Ranges           ; Section 14.5
                | Age                     ; Section 14.6
                | ETag                    ; Section 14.19
                | Location                ; Section 14.30
                | Proxy-Authenticate      ; Section 14.33
                | Retry-After             ; Section 14.37
                | Server                  ; Section 14.38
                | Vary                    ; Section 14.44
                | WWW-Authenticate        ; Section 14.47
  1. 實體頭(Entity Header Fields):如果消息帶有消息體,實體頭用來作為元信息;如果沒有消息體,就是為了描述請求的資源的信息。
entity-header  = Allow                    ; Section 14.7
               | Content-Encoding         ; Section 14.11
               | Content-Language         ; Section 14.12
               | Content-Length           ; Section 14.13
               | Content-Location         ; Section 14.14
               | Content-MD5              ; Section 14.15
               | Content-Range            ; Section 14.16
               | Content-Type             ; Section 14.17
               | Expires                  ; Section 14.21
               | Last-Modified            ; Section 14.29
               | extension-header

消息體(Message Body)和實體主體(Entity Body)

如果有Transfer-Encoding頭,那么消息體解碼完了就是實體主體,如果沒有Transfer-Encoding頭,消息體就是實體主體。

  message-body = entity-body
                | <entity-body encoded as per Transfer-Encoding>

在request消息中,消息頭中含有Content-Length或者Transfer-Encoding,標(biāo)識會有一個消息體跟在后邊。如果請求的方法不應(yīng)該含有消息體(如OPTION),那么request消息一定不能含有消息體,即使客戶端發(fā)送過去,服務(wù)器也不會讀取消息體。

在response消息中,是否存在消息體由請求方法和返回碼來共同決定。像1xx,204,304不會帶有消息體。

消息體的長度

消息體長度的確定有一下幾個規(guī)則,它們順序執(zhí)行:
1. 所有不應(yīng)該返回內(nèi)容的Response消息都不應(yīng)該帶有任何的消息體,消息會在第一個空行就被認(rèn)為是終止了。
2. 如果消息頭含有Transfer-Encoding,且它的值不是identity,那么消息體的長度會使用chunked方式解碼來確定,直到連接終止。
3. 如果消息頭中有Content-Length,那么它就代表了entity-length和transfer-length。如果同時含有Transfer-Encoding,則entity-length和transfer-length可能不會相等,那么Content-Length會被忽略。
4. 如果消息的媒體類型是multipart/byteranges,并且transfer-length也沒有指定,那么傳輸長度由這個媒體自己定義。通常是收發(fā)雙發(fā)定義好了格式, HTTP1.1客戶端請求里如果出現(xiàn)Range頭域并且?guī)в卸鄠€字節(jié)范圍(byte-range)指示符,這就意味著客戶端能解析multipart/byteranges響應(yīng)。
5. 如果是Response消息,也可以由服務(wù)器來斷開連接,作為消息體結(jié)束。
從消息體中得到實體主體,它的類型由兩個header來定義,Content-Type和Content-Encoding(通常用來做壓縮)。如果有實體主體,則必須有Content-Type,如果沒有,接收方就需要猜測,猜不出來就是用application/octet-stream。

HTTP連接

HTTP1.1的連接默認(rèn)使用持續(xù)連接(persistent connection),持續(xù)連接指的是,有時是客戶端會需要在短時間內(nèi)向服務(wù)端請求大量的相關(guān)的資源,如果不是持續(xù)連接,那么每個資源都要建立一個新的連接,HTTP底層使用的是TCP,那么每次都要使用三次握手建立TCP連接,將造成極大的資源浪費(fèi)。

持續(xù)連接可以帶來很多的好處:

1. 使用更少的TCP連接,對通信各方的壓力更小。
2. 可以使用管道(pipeline)來傳輸信息,這樣請求方不需要等待結(jié)果就可以發(fā)送下一條信息,對于單個的TCP的使用更充分。
3.  流量更小
4. 順序請求的延時更小。
5. 不需要重新建立TCP連接就可以傳送error,關(guān)閉連接等信息。

HTTP1.1的服務(wù)器使用TCP的流量控制來控制HTTP的流量,HTTP1.1的客戶端在收到服務(wù)器連接中發(fā)過來的error信息,就要馬上關(guān)閉此鏈接。關(guān)于HTTP連接還有很多細(xì)節(jié),之后再詳述。

WebSocket

只從RFC發(fā)布的時間看來,WebSocket要晚近很多,HTTP 1.1是1999年,WebSocket則是12年之后了。WebSocket協(xié)議的開篇就說,本協(xié)議的目的是為了解決基于瀏覽器的程序需要拉取資源時必須發(fā)起多個HTTP請求和長時間的輪訓(xùn)的問題……而創(chuàng)建的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 組織:中國互動出版網(wǎng)(http://www.china-pub.com/) RFC文檔中文翻譯計劃(http://...
    Palomar閱讀 1,591評論 0 6
  • 那天和boss聊天,不經(jīng)意間提到了Meteor,然后聊到了WebSocket,然后就有了以下對話,不得不說,看問題...
    TheAlchemist閱讀 49,761評論 10 166
  • 深入淺出HTTP協(xié)議(WEB開發(fā)和面試必備) 1.基礎(chǔ)概念篇 a.簡介 HTTP是Hyper Text Trans...
    半世韶華憶闌珊閱讀 1,236評論 0 7
  • 一、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,413評論 6 152