詳解http協議

HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用于從服務器傳輸超文本到本地瀏覽器的傳送協議。HTTP 是基于 TCP/IP 協議通信協議來傳遞數據(HTML 文件、圖片文件、查詢結果等)。它不涉及數據包(packet)傳輸,主要規定了客戶端和服務器之間的通信格式,默認使用80端口


http.png

一、Http的特點

  • 簡單快速:客戶端只需傳輸請求方法(get、post等)和路徑 ,通信速度很快
  • 靈活:http允許傳輸任意類型的數據
  • 無連接:即限制每次連接只處理一個請求,客戶端在收到服務器的連接應答后,即斷開連接
  • 無狀態:http協議不會對請求和響應之間的通信狀態進行保存,這一次的請求和下一次的請求沒有依賴的關系,是相互獨立的。協議本身不保存之前的請求或者報文 。這樣http才能快速 簡潔

二、Http報文

Http報文包括請求報文和響應報文
請求報文由請求行(request line)、請求頭(header)、空行和請求體四個部分組成。
響應報文由狀態行、響應頭部、空行和響應體四個部分組成。

請求報文和響應報文都是由開始行(對于請求報文,開始行就是請求行,對于響應報文,開始行就是狀態行),消息報頭(可選),空行(只有CRLF的行),消息正文(可選)組成。

HTTP消息報頭包括普通報頭、請求報頭、響應報頭、實體報頭

  • 消息報頭-普通報頭 : 在普通報頭中,有少數報頭域用于所有的請求和響應消息,但并不用于被傳輸的實體,只用于傳輸的消息。

Cache-Control 用于指定緩存指令,緩存指令是單向的(響應中出現的緩存指令在請求中未必會出現),且是獨立的(一個消息的緩存指令不會影響另一個消息處理的緩存機制),HTTP1.0使用的類似的報頭域為Pragma。
請求時的緩存指令包括: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.
eg:為了指示IE瀏覽器(客戶端)不要緩存頁面,服務器端的JSP程序可以編寫如下:response.sehHeader("Cache-Control","no-cache");
//response.setHeader("Pragma","no-cache");作用相當于上述代碼,通常兩者//合用
這句代碼將在發送的響應消息中設置普通報頭域:Cache-Control:no-cache

  • 消息報文-實體報頭 : 請求和響應消息都可以傳送一個實體。一個實體由實體報頭域和實體正文組成,但并不是說實體報頭域和實體正文要在一起發送,可以只發送實體報頭域。實體報頭定義了關于實體正文(eg:有無實體正文)和請求所標識的資源的元信息。

常用的實體報頭
Cache—Control:指定緩存指令,分為請求或響應時的緩存指令,緩存指令是單向的,C例如JSP代碼:response.setHeader(“Cache—Control”,”no—cache”);
Date:消息產生的日期和時間,客戶端只有在發送消息中包含了消息正文的時候,才發送Date報頭域,服務器端響應總是包含Date報頭域。
Connection:允許發送者指定連接的選項,服務器響應后的狀態
Pragmatic:用于包含特定實現(implementation—specific)的指令,Pragma:no—cache與HTTP1.1版的Cache—Control:no—cache作用相同

請求報文

image.png
  • 請求報文-開始行-請求行:包括請求方法、請求資源路徑、http協議版本
  • 請求報文-消息報頭-請求頭:由關鍵字/值對組成 請求頭部通知服務器有關于客戶端請求的信息
    ? 它包含許多有關的客戶端環境和請求正文的有用信息。其中比如:

Connection,HTTP/1.1增加的,使用keepalive,即持久連接,一個連接可以發多個請求;
Accept: 瀏覽器可接受的MIME類型。
Accept-Charset:瀏覽器可接受的字符集。
Accept-Encoding:瀏覽器能夠進行解碼的數據編碼方式,比如gzip。Servlet能夠向支持gzip的瀏覽器返回經gzip編碼的HTML頁面。許多情形下這可以減少5到10倍的下載時間。
Accept-Language:瀏覽器所希望的語言種類,當服務器能夠提供一種以上的語言版本時要用到。
Authorization:授權信息,通常出現在對服務器發送的WWW-Authenticate頭的應答中。
Content-Length:表示請求消息正文的長度。
Host: 客戶機通過這個頭告訴服務器,想訪問的主機名。Host頭域指定請求資源的Intenet主機和端口號,必須表示請求url的原始服務器或網關的位置。HTTP/1.1請求必須包含主機頭域,否則系統會以400狀態碼返回。
If-Modified-Since:客戶機通過這個頭告訴服務器,資源的緩存時間。只有當所請求的內容在指定的時間后又經過修改才返回它,否則返回304“Not Modified”應答。
Referer:客戶機通過這個頭告訴服務器,它是從哪個資源來訪問服務器的(防盜鏈)。包含一個URL,用戶從該URL代表的頁面出發訪問當前請求的頁面。
User-Agent:User-Agent頭域的內容包含發出請求的用戶信息。瀏覽器類型,如果Servlet返回的內容與瀏覽器類型有關則該值非常有用。
Cookie:客戶機通過這個頭可以向服務器帶數據,這是最重要的請求頭信息之一。
Pragma:指定“no-cache”值表示服務器必須返回一個刷新后的文檔,即使它是代理服務器而且已經有了頁面的本地拷貝。
From:請求發送者的email地址,由一些特殊的Web客戶程序使用,瀏覽器不會用到它。
Connection:處理完這次請求后是否斷開連接還是繼續保持連接。如果Servlet看到這里的值為“Keep- Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久連接),它就可以利用持久連接的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點,Servlet需要在應答中發送一個Content-Length頭,最簡單的實現方法是:先把內容寫入 ByteArrayOutputStream,然后在正式寫出內容之前計算它的大小。
Range:Range頭域可以請求實體的一個或者多個子范圍。例如,
表示頭500個字節:bytes=0-499
表示第二個500字節:bytes=500-999
表示最后500個字節:bytes=-500
表示500字節以后的范圍:bytes=500-
第一個和最后一個字節:bytes=0-0,-1
同時指定幾個范圍:bytes=500-600,601-999
但是服務器可以忽略此請求頭,如果無條件GET包含Range請求頭,響應會以狀態碼206(PartialContent)返回而不是以200 (OK)。UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE瀏覽器所發送的非標準的請求頭,表示屏幕大小、顏色深度、操作系統和CPU類型

  • 空行:最后一個請求頭之后是一個空行,這個行非常重要,它表示請求頭已經結束,接下來的是請求正文
  • 請求體:若方法字段是GET,則此項為空,沒有數據
    ? 若方法字段是POST,則通常來說此處放置的就是要提交的數據
    ? 比如要使用POST方法提交一個表單,其中有user字段中數據為“admin”, password字段為123456,那么這里的請求數據就是 user=admin&password=123456,使用&來連接各個字段。

響應報文

image.png
  • 響應報文-開始行-響應行:響應行一般由協議版本、狀態碼及其描述組成 比如 HTTP/1.1 200 OK
    其中協議版本HTTP/1.1或者HTTP/1.0,200就是它的狀態碼,OK則為它的描述。

  • 響應報文-消息報頭-響應頭:響應頭用于描述服務器的基本信息,以及數據的描述,服務器通過這些數據的描述信息,可以通知客戶端如何處理等一會兒它回送的數據。
    設置HTTP響應頭往往和狀態碼結合起來。例如,有好幾個表示“文檔位置已經改變”的狀態代碼都伴隨著一個Location頭,而401(Unauthorized)狀態代碼則必須伴隨一個WWW-Authenticate頭。然而,即使在沒有設置特殊含義的狀態代碼時,指定應答頭也是很有用的。應答頭可以用來完成:設置Cookie,指定修改日期,指示瀏覽器按照指定的間隔刷新頁面,聲明文檔的長度以便利用持久HTTP連接等其他任務。

Allow:服務器支持哪些請求方法(如GET、POST等)。
Content-Encoding:文檔的編碼(Encode)方法。只有在解碼之后才可以得到Content-Type頭指定的內容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE4、IE5才支持它。因此,Servlet應該通過查看Accept-Encoding頭(即request.getHeader(“Accept- Encoding”))檢查瀏覽器是否支持gzip,為支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。
Content-Length:表示內容長度。只有當瀏覽器使用持久HTTP連接時才需要這個數據。如果你想要利用持久連接的優勢,可以把輸出文檔寫入 ByteArrayOutputStram,完成后查看其大小,然后把該值放入Content-Length頭,最后通過byteArrayStream.writeTo(response.getOutputStream()發送內容。
Content- Type:表示后面的文檔屬于什么MIME類型。Servlet默認為text/plain,但通常需要顯式地指定為text/html。由于經常要設置 Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。
Date:當前的GMT時間,例如,Date:Mon,31Dec200104:25:57GMT。Date描述的時間表示世界標準時,換算成本地時間,需要知道用戶所在的時區。你可以用setDateHeader來設置這個頭以避免轉換時間格式的麻煩。
Expires:告訴瀏覽器把回送的資源緩存多長時間,-1或0則是不緩存。
Last-Modified:文檔的最后改動時間。客戶可以通過If-Modified-Since請求頭提供一個日期,該請求將被視為一個條件GET,只有改動時間遲于指定時間的文檔才會返回,否則返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。
Location:這個頭配合302狀態碼使用,用于重定向接收者到一個新URI地址。表示客戶應當到哪里去提取文檔。Location通常不是直接設置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼為302。
Refresh:告訴瀏覽器隔多久刷新一次,以秒計。
Server:服務器通過這個頭告訴瀏覽器服務器的類型。Server響應頭包含處理請求的原始服務器的軟件信息。此域能包含多個產品標識和注釋,產品標識一般按照重要性排序。Servlet一般不設置這個值,而是由Web服務器自己設置。
Set-Cookie:設置和頁面關聯的Cookie。Servlet不應使用response.setHeader(“Set-Cookie”, …),而是應使用HttpServletResponse提供的專用方法addCookie。
Transfer-Encoding:告訴瀏覽器數據的傳送格式。
WWW-Authenticate:客戶應該在Authorization頭中提供什么類型的授權信息?在包含401(Unauthorized)狀態行的應答中這個頭是必需的。例如,response.setHeader(“WWW-Authenticate”, “BASIC realm=\”executives\”“)。注意Servlet一般不進行這方面的處理,而是讓Web服務器的專門機制來控制受密碼保護頁面的訪問。
注:設置應答頭最常用的方法是HttpServletResponse的setHeader,該方法有兩個參數,分別表示應答頭的名字和值。和設置狀態代碼相似,設置應答頭應該在發送任何文檔內容之前進行。
setDateHeader方法和setIntHeadr方法專門用來設置包含日期和整數值的應答頭,前者避免了把Java時間轉換為GMT時間字符串的麻煩,后者則避免了把整數轉換為字符串的麻煩。
HttpServletResponse還提供了許多設置
setContentType:設置Content-Type頭。大多數Servlet都要用到這個方法。
setContentLength:設置Content-Length頭。對于支持持久HTTP連接的瀏覽器來說,這個函數是很有用的。
addCookie:設置一個Cookie(Servlet API中沒有setCookie方法,因為應答往往包含多個Set-Cookie頭)。

  • 響應體:響應體就是響應的消息體,如果是純數據就是返回純數據,如果請求的是HTML頁面,那么返回的就是HTML代碼,如果是JS就是JS代碼,如此之類。

三、HTTP請求方法

  • GET 請求指定的頁面信息,并返回實體主體。
  • HEAD 類似于get請求,只不過返回的響應中沒有具體的內容,用于獲取報頭
  • POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。
  • PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容。
  • DELETE 請求服務器刪除指定的頁面。

四、GET與POST區別

  • 參數位置不同:get參數在請求url中,post在請求體中
  • 大小不同 get在url中的參數是有長度限制的,post沒有限制
  • get請求只能進行url編碼,而post支持多種編碼方式
  • get請求會瀏覽器主動cache,而post支持多種編碼方式。
  • get請求參數會被完整保留在瀏覽歷史記錄里,而post中的參數不會被保留。
  • get產生一個TCP數據包;post產生兩個TCP數據包。

五、Http狀態碼

1xx:指示信息--表示請求已接收,繼續處理
2xx:成功--表示請求已被成功接收、理解、接受
3xx:重定向--要完成請求必須進行更進一步的操作
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現
5xx:服務器端錯誤--服務器未能實現合法的請求

常見的狀態碼:

200:成功——比如GET請求,請求的資源會作為響應實體返回 , 而HEAD請求,信息只存在于響應報文首部header,因為它不會返回報文實體,只返回報文首部 、 而對于POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
204:No Content 請求已成功處理,但是沒有內容返回,返回的響應報文中沒有報文實體
307和304(我不給你這個資源,自己拿緩存)
206:Partial Content 表示服務器已經完成了部分GET請求(客戶端進行了范圍請求) 響應報文中包含Content-Range指定范圍的實體內容
301: Moved Permanently 永久重定向,表示請求的資源已經永久的搬到了其他位置 就是說資源已經被分配了新的URI
302 :Found 臨時重定向。表示請求的資源臨時搬到了其他位置,請求的資源暫時被配到到了新的URI 新的臨時URI應該提示在響應報文的Location首部字段
303:See Other 請求資源存在另一個URI,應使用GET定向獲取請求資源 (用get重新獲?。?br> 304:Not Modified 表示客戶端發送附帶條件的請求(GET方法請求報文中的IF…)時,條件不滿足
返回304時,不包含任何響應主體
400:Bad Request 表示請求報文存在語法錯誤或參數錯誤,服務器不理解 服務器不應該重復提交這個請求 ,需要修改請求內容后再次發送
401:Unauthorized 發送的請求需要有HTTP認證信息或者是認證失敗了 返回401的響應必須包含一個適用于被請求資源的WWW-Authenticate首部以質詢用戶信息
403:Forbidden 表示對請求資源的訪問被服務器拒絕,服務器可以對此作出解釋,也可以不解釋 比如說你可能沒有訪問權限
404: Not Found 服務器找不到你請求的資源
500 : Internal Server Error 表示服務器執行請求的時候出錯了 可能是Web應用有bug或臨時故障
502: Bad Gateway 對用戶訪問請求的響應超時造成的 Web 服務器用作網關或代理服務器時收到了無效響應 即連接超時 我們向服務器發送請求 由于服務器當前鏈接太多,導致服務器方面無法給于正常的響應,產生此類報錯
503: Service Unavailable 表示服務器超負載或正停機維護,無法處理請求。

六、持久連接

  1. 為什么需要持久連接
    HTTP協議的初始版本中,每進行一次HTTP通信就要斷開一次TCP連接。以當年的通信情況來說,因為都是些容量很小的文本傳輸,所以即使這樣也沒有多大問題??呻S著 HTTP 的 普及,文檔中包含大量圖片的情況多了起來。比如,使用瀏覽器瀏覽一個包含多張圖片的 HTML 頁面時,在發送請求訪問 HTML 頁面資源的同時,也會請 求該 HTML 頁面里包含的其他資源。因此,每次的請求都會造成無謂的 TCP 連接建立和斷開,增加通信量的 開銷。
    image.png
  2. 持久連接的特點
    為解決上述 TCP 連接的問題,HTTP/1.1 和一部分的 HTTP/1.0 想出了持久連接(HTTP Persistent Connections,也稱為 HTTP keep-alive 或 HTTP connection reuse)的方法。持久連接的特點是,只要任意一端沒有明確提出斷開連接,則保持TCP連接狀態。
    持久連接的好處在于減少了 TCP 連接的重復建立和斷開所造成的額外開銷,減輕了服務器端的負載。另外, 減少開銷的那部分時間,使 HTTP 請求和響應能夠更早地結束,這樣 Web 頁面的顯示速度也就相應提高了。
    在 HTTP/1.1 中,所有的連接默認都是持久連接,但在 HTTP/1.0 內并未標準化。雖然有一部分服務器通過非 標準的手段實現了持久連接,但服務器端不一定能夠支持持久連接。毫無疑問,除了服務器端,客戶端也需 要支持持久連接。
image.png

七、一次完整的HTTP請求所經歷的7個步驟

HTTP通信機制是在一次完整的HTTP通信過程中,Web瀏覽器與Web服務器之間將完成下列7個步驟:

  1. 建立TCP連接
    在HTTP工作開始之前,Web瀏覽器首先要通過網絡與Web服務器建立連接,該連接是通過TCP來完成的,該協議與IP協議共同構建 Internet,即著名的TCP/IP協議族,因此Internet又被稱作是TCP/IP網絡。HTTP是比TCP更高層次的應用層協議,根據規則, 只有低層協議建立之后才能,才能進行更層協議的連接,因此,首先要建立TCP連接,一般TCP連接的端口號是80。

  2. Web瀏覽器向Web服務器發送請求命令
    一旦建立了TCP連接,Web瀏覽器就會向Web服務器發送請求命令。例如:GET/sample/hello.jsp HTTP/1.1。

  3. Web瀏覽器發送請求頭信息
    瀏覽器發送其請求命令之后,還要以頭信息的形式向Web服務器發送一些別的信息,之后瀏覽器發送了一空白行來通知服務器,它已經結束了該頭信息的發送。

  4. Web服務器應答
    客戶機向服務器發出請求后,服務器會客戶機回送應答, HTTP/1.1 200 OK ,應答的第一部分是協議的版本號和應答狀態碼。

  5. Web服務器發送應答頭信息
    正如客戶端會隨同請求發送關于自身的信息一樣,服務器也會隨同應答向用戶發送關于它自己的數據及被請求的文檔。

  6. Web服務器向瀏覽器發送數據
    Web服務器向瀏覽器發送頭信息后,它會發送一個空白行來表示頭信息的發送到此為結束,接著,它就以Content-Type應答頭信息所描述的格式(json等)發送用戶所請求的實際數據。

  7. Web服務器關閉TCP連接
    一般情況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP連接,然后如果瀏覽器或者服務器在其頭信息加入了這行代碼:
    Connection:keep-alive (保持連接)
    TCP連接在發送后將仍然保持打開狀態,于是,瀏覽器可以繼續通過相同的連接發送請求。保持連接節省了為每個請求建立新連接所需的時間,還節約了網絡帶寬。

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

推薦閱讀更多精彩內容