注:本文是HTTP權威指南這本書讀的過程中記錄下來的一些case
一、http概述
媒體類型 MIME 例如 image/jpeg 有數百個MIME類型
對於URI和URL的理解: http://localhost:8080/login/index.html
帶顏色部分可以理解爲URI 全部可以理解爲URL 而URL一定是URI URL是URI的一個子集、URL說明了協議,服務器,和本地資源。 服務器資源名稱被稱爲URI
事務
一個HTTP事務是由一個HTTP請求和一個HTTP響應組成的,通過HTTP報文來進行通信。報文是通過傳輸協議TCP傳輸的。TCP提供無差錯的數據傳輸,按序傳輸。未分段的數據流(可以在任意時刻以任意size發送數據)
HTTP使用了TCP/IP傳輸協議,它是基於文本的,沒有使用那些難以理解的二進制格式。
使用Telnet可以連接到某個TCP端口,並向這個端口發送數據,端口返回的數據會顯示出來。
Web的結構組件
1.代理:位於客戶端和服務器之間的HTTP中間實體。 例如nginx、
2.緩存:HTTP的倉庫,將資源在一定時間內保存到裏客戶端更近的地方(例如代理服務器)
3.網關:連接其他應用程序的特殊Web服務器。一箇中間實體。
4.隧道:對HTTP報文進行盲轉發的特殊代理。 例如:HTTPS --- HTTP+SSL
5.Agent代理:發起自動HTTP請求的半智能Web客戶端。 例如:瀏覽器
二、URL與資源
URL由多部分構成的通用格式組成
scheme://user:password@host:port/path?query#frag
scheme是協議,例如:http user和password是資源訪問需要的用戶名和密碼。後面是我們熟悉的主機端口資源和query參數以及錨點。
用戶名密碼例如:ftp://user:[email protected]/upload/a.jpg
URL中,通過一種轉義機制來表示不安全字符的,這種轉義包含一個%,後面跟着兩個表示字符ASCLL碼的十六進制數。
如果資源不存在就會返回404了,有一個叫做統一資源名的URN概念、無論資源還在不在那個路徑,URN都能標記到。URN在目前還沒有被標準化的使用。
三、HTTP報文
報文是客戶端和服務端通信的載體。報文永遠向下遊流動。這個挺抽象的,上游和下游與接收者和發送者有關。 接收報文的就是下游節點。
報文由起始行,首部(header)和主體(body)組成。報文分爲請求報文和響應報文。格式如下
請求報文:
<method> <request-url> <version> ----起始行
<headers> ----首部
<entity-body> ----主體
響應報文:
<version> <status> <reason-pharse> ----起始行
<headers> ----首部
<entity-body> ----主體
方法(method):GET、POST、DELETE、PUT等等、
請求URL(request-url)
版本(version):HTTP/<major>.<minor>
狀態碼(status):請求的結果成功與否、
原因短語(reason-pharse):HTTP 200 OK 中那個OK
首部(header)和主體(body)這個是編程常編碼的。
方法
現在web開發有一個比較規範化的Restful規範。
GET:從服務器請求資源。比如獲取訂單信息。只獲取不修改。
HEAD:在響應中只返回header而不返回body
@RequestMapping(value = "/head",method = RequestMethod.HEAD)
public String getHead(){
return "success"; //最終沒有輸出success
}
@RequestMapping(value = "/get",method = RequestMethod.GET)
public String getMes(){
return "success";
}
PUT:讓服務器用請求的主體部分來創建一個由所請求的URL命名的新文檔。如果那個URL已經存在的話,就用這個主體代替。可以理解爲save。存在即更新,不存在即插入、
POST:通常會用它來支持HTML的表單。將表單數據發送到服務器,由服務器決定發送到哪裏。
TRACE:會在目的服務器發起一個迴環診斷。最終返回整個過程中,被哪些服務器修改過並附帶請求報文。(感覺沒人用)
DELETE:刪除URL中所指定的資源。
狀態碼
100-101:提示信息
200-206:成功
300-305:重定向
400-415:客戶端錯誤
500-505:服務器錯誤。
以上是已定義的狀態碼。 在百範圍內就是一類狀態碼。
例如 401:unauthorized 未授權。需要輸入用戶名和密碼。
100~199:信息性狀態碼。這個目前網站開發過程中使用的並不多(沒見過)。
200~299:成功狀態碼。 目前見到最多的就是200 表示請求沒問題,實體的主體部分包含了所請求的資源。
300~399:重定向狀態碼。
301: Moved Permanently 永久重定向。在請求的URL已經被移除,響應的location首部中應該包含資源現在所處的URL
302: Found 臨時重定向。客戶端使用Location首部給出的URL來臨時定位資源。將來的請求仍然使用老的URL。(307代替)這個在http1.0版本使用
303: See Other 告知客戶端應該用另一個URL來獲取資源。新的URL位於響應報文的Location首部(header)。這樣我們可以通過新的URL來獲取最初請求的響應資源。
304: Not Modified 資源未被修改。帶有這個狀態碼的響應報文不應該包含實體的主體部分。
307: 客戶端應該用另一個URL來獲取資源。新的URL位於響應報文的Location首部(header)。這樣我們可以通過新的URL來獲取最初請求的響應資源。(HTTP1.1)
307、303、302看起來差不多。區別在於HTTP的版本1.0還是1.1
400~499:客戶端錯誤狀態碼。
400:Bad Request 告訴客戶端他發送一個錯誤的請求。一般參數錯就是這個了。
401:Unauthorized 與適當的header一起返回,在這些header中請求客戶端在獲取對資源的訪問權之前,對自己認證。
403:Forbidden 請求被服務器拒絕了。
404:Not Found 沒找到請求的URL。
405:Method Not Allowed 發起的請求中帶有所請求的URL不支持的方法。
409:Conflict 用於說明請求可能在資源上引發一些衝突時返回這個狀態碼。
500~599:服務器錯誤狀態碼。
500:Internal Server Error 服務器內部錯誤。
501:Not Implemented 客戶端發起的請求超出服務器的能力範圍(比如,使用不認識的請求方法)
502:Bad Gateway 作爲代理或網關使用的服務器從請求響應鏈的下一條鏈路上收到一條僞響應,代理出現問題。(比如nginx的問題,返回502)
503:Servicec Unavaliable 服務器現在無法爲請求提供服務,但將來可以。如果服務器知道資源什麼時候可以用就會在響應報文的header中寫入 Retry-After (比如 客戶端反覆發送請求造成,HTTP服務器拒絕接受客戶端請求)
504:Gateway Timeout 在等待另一個服務器對其請求作出響應時超時了。(比如客戶端訪問nginx,nginx訪問Tomcat超時)
首部(Header)
首部分爲如下五種。
1.通用首部:既可以出現在請求報文中,又可以出現在響應報文中。
請求報文和響應報文中都可以存在的header 比如 Date
2.請求首部:提供更多有關請求的信息。
請求報文中有一個比較有意思的Accept 這個是告訴服務器,客戶端想要啥樣不想要啥樣。 比如 Accept */* 告訴服務器接收所有的類型。 Accept-Charset 告訴服務器能夠發送那些字符集。
User-Agent 告訴服務器發起請求的應用程序名稱。
還有一些安全的header
Authorization 包含了客戶端提供給服務器,以便對其認證的數據。
Cookie 客戶端向服務器發送一個令牌。
Proxy-Authorization 在與代理進行認證的時候使用的。
3.響應首部:提供更多有關響應的信息。
響應header爲客戶端提供一些額外信息,比如誰在發送響應,響應者的功能、甚至與響應相關的一些指令。
server 服務器應用程序軟件的名稱和版本。
4.實體首部:描述主體的長度和內容,或者資源自身。
實體首部可以用來描述有關實體和內容的大量信息。從有關對象類型的信息,到能夠對資源使用的各種有效的請求方法。
Allow 列出了可以對此實體執行的請求方法。
Location 比如 302 /303/307指向的重定向資源。
還有一系列Content相關的header。比如Content-Type 這個主體的對象類型。application/json 等。
Content-Length 主體(response)的長度。
Expires 實體不在有效,要從原始的源端再次獲取此實體的日期和時間。
Last-Modified這個實體最後一次唄修改的日期和時間。
5.擴展首部:規範中沒有定義的新首部。
四、連接管理
HTTP連接是HTTP報文傳輸的關鍵通道。
TCP爲HTTP提供了一條可靠的比特傳輸管道,從TCP連接一端填入的字節會從另一端以原有的順序正確的傳送出來。
WEB瀏覽器通過TCP連接與WEB服務器進行交互。
TCP流是分段的,由IP分組傳送
tcp的數據是通過名爲IP分組(或IP數據報)的小數據塊來發送的。保證接收順序跟傳入順序一致。
HTTP---TCP----IP---網絡接口 https---SSL---TCP---IP---網絡接口
源ip&源端口號&目的ip&目的端口號 四個值唯一定位了一條連接。
socket套接字隱藏掉了TCP/IP握手等細節。
僞代碼表示套接字API凸顯的客戶端和服務端實現HTTP事務時所應執行的步驟。
1.創建新的套接字socket。
2.將套接字綁定到某一端口bind(80)
3.允許套接字進行連接 listen
4.等待連接 accept
5.客戶端創建套接字並connect到這個服務器的ip:port
6.服務端讀取連接read 客戶端發送http請求。
7.服務端處理請求報文,並返回http響應報文
8.客戶端處理http響應。
9.雙方關掉連接。
對TCP性能的考慮
1.HTTP事務的時延。
一個http的過程--------
(1)客戶端的URL域名進行DNS解析查詢。 -----如果沒有訪問過,DNS解析時間會相對時間長一點。
(2)客戶端與目的ip服務器建立連接(TCP握手)。 -----隨着併發多,這個時間會加長一些。
(3)HTTP向服務器發出請求報文
(4)服務器處理請求報文 ------這是最耗時的。
(5)服務器向客戶端發送響應報文。
(6)客戶端處理響應報文。關閉連接。
TCP連接
(1)請求新的TCP連接時,客戶端要向服務端發送一個小的TCP分組,這個分組設置了一個特殊的SYN標記,說明這是一個連接請求。
(2)如果服務器接受了連接,就會對一些連接參數進行計算,並向客戶端回送一個TCP分組。這個分組中的SYN和ACK標記都被置位。說明連接請求已經被接受。
(3)最後,客戶端向服務器發送一條確認信息,通知他連接已經成功建立,現代的TCP棧都允許客戶端在這個確認分組中發送數據。
延遲確認
由於因特網自身無法確保可靠的分組傳輸。所以TCP實現了自己的確認機制來確保數據的成功傳輸。
每個TCP段都有一個TCP段序列號和數據完整性校驗和。每個段的接收者收到完好的段時,都會向發送者回送小的確認分組,如果發送者沒有在指定的窗口時間內接收到確認信息,發送者就會認爲分組被破壞或丟失,並重新發送數據。
上述小的確認分組一般結合輸出的數據分組一同發送,有效的利用網絡。如果時間段內沒有輸出數據分組,就單獨發送這個小的確認分組。
TCP慢啓動
TCP數據傳輸的性能還取決於TCP連接的使用期。TCP連接會隨着時間進行自我調諧,起初會限制連接的最大速度。如果數據傳輸成功會隨着時間的推移提高傳輸的速度。被稱爲TCP的慢啓動。用於防止因特網的突然過載。
Nagle算法
Nagle算法試圖在發送一個分組之前,將大量TCP數據綁定在一起,以提供網絡效率。
如果發送的小分組無法沾滿Nagle所指定的大小就會產生延遲。 HTTP通常會禁用Nagle算法。
HTTP連接的處理
一些提高HTTP連接性能的技術
(1)並行連接:通過多條TCP連接發起併發的HTTP請求。
(2)持久連接:重用TCP連接,以消除連接及關閉時延。
(3)管道化連接:通過共享的TCP連接發起併發的HTTP請求。
並行連接相對串行要快一些,不用等上一條事務走完就走下一條事務。
持久連接會在事務處理完成後繼續保持連接。持久連接不會像並行連接那樣創建那麼多的連接,持久連接建立連接會保持一段時間,減少了創建連接產生的開銷,但是會佔住TCP連接不放。
持久連接有兩種類型:HTTP/1.0 keep-alive 和 HTTP/1.1 persistent
keep-alive在請求報文的header中發送,並在響應報文的header中也存在才建立長連接。Connection: Keep-Alive
http1.1的長連接默認是開啓的,只有服務端往響應報文的header中寫了Connection:close 纔會關閉。當然也可以主動關。
管道化連接:這個是持久連接的基礎上,順序發送請求入管道, 要求響應也是跟請求順序一致。(感覺應用場景不多)
關於HTTP的關閉。套接字調用close()