http協議學習-總結
第一部分 HTTP:WEB的基礎
第一章 HTTP概述
媒體型別
http給每種要通過web傳輸的物件都打上了名為MIME(Multipurpose Internet Mail Extension,多用途因特網郵件擴充套件)型別的資料格式標籤。
Web伺服器會為所有HTTP物件資料附加一個MIME型別。當Web瀏覽器從伺服器中取回一個物件時,回去檢視相關的MIME型別,看看它是否知道應該如何處理這個物件。
MIME型別是一種文字標記,表示一種主要的物件型別和一個特定的子型別,中間由斜槓來分隔。
1、HTML格式的文字文件由 text/html 型別來標記
2、普通的ASCII文字文件由 text/plain 型別來標記
3、JPEG版本的圖片為 image/jpeg 型別
4、GIF格式的圖片為 image/gif型別
5、Apple的QuickTime電影為 video/quidktime 型別
6、微軟的PowerPoint演示檔案為 application/vnd.ms-powerpoint 型別
URI
伺服器資源名被稱為統一資源識別符號(Uniform Resource Identifier,URI).URI就像因特網上的郵政地址一樣,在世界範圍內唯一標識並定位資訊資源。
例如一個圖片資源的URI:
http://www.baidu.com/specials/sky.gif
當給定了URI,HTTP就可以解析出物件。URI有兩種形式,分別稱為URL和URN。
URL
統一資源定位符(URL)是資源識別符號最常見形式。它描述了一臺特定伺服器上的某資源的特定位置。
URL說明了協議、伺服器和本地資源。如下圖:
URL例項:
大部分的URL都遵循一種標準格式,這種格式包含三個部分:、
①方案(scheme),說明了訪問資源所使用的協議型別。這部分通常是HTTP協議(http://)
②給出伺服器的因特網地址(www.baidu.com)
③其餘部分指定了WEB伺服器上的某個資源(/specials/sky.gif)
現在,幾乎所有的URI都是URL。
URN
URI的第二種形式就是URN(統一資源名)。URN是作為特定內容的唯一名稱使用的,與目前的資源所在地無關。使用這些與位置無關的URN,就可以將資源四處搬移。通過URN,還可以用同一個名字通過多種網路訪問協議來訪問資源。
例如:RFC 2141 無論在何處,甚至可以複製到多個地方,都可以用以下URN來命名:
urn:ietf:rfc:2141
URN仍處於試驗階段。
*事務*
一個HTTP事務由一條請求命令和一個響應結果組成。這種通訊是通過名為HTTP報文的格式化資料塊進行的。
方法
HTTP支援幾種不同的請求命令,這些命令被稱為HTTP方法(HTTP method)。
常見的HTTP方法:
GET—-從伺服器向客戶的傳送命名資源
PUT—-將來自客戶的的資料儲存到一個命名的伺服器資源中去
DELETE—-從伺服器中刪除命名資源
POST—-將客戶端資料傳送到一個伺服器閘道器應用程式
HEAD—-僅傳送命名資源響應中的HTTP首部
狀態碼
每條HTTP響應報文返回時都會攜帶一個狀態碼。狀態碼是一個三位數字的程式碼,告知客戶端請求是否成功,或者是否需要採取其他動作。
常見狀態碼:
200—-OK,文件返回正確
302—-Redirect,重定向,到其他地方獲取資源
404—-Not Found,無法找到這個資源
WEB頁面中可以包含多個物件
一個WEB頁面是一組資源的集合。web瀏覽器會發布一系列HTTP事務來獲取並顯示一個包含了豐富資源的頁面。
*報文*
HTTP報文是由一行一行的簡單字串組成。它是純文字,並非二進位制程式碼。
HTTP報文包含以下三個部分:
1、起始行
報文的第一行,在請求報文中用來說明要做些什麼。在響應報文中說明出現了什麼情況。
2、首部欄位
起始行後面有零個或者多個首部欄位。每個欄位都包含一個名字和一個值,為了便於解析,兩者之間用冒號(:)分隔。首部以一個空行結束。
3、主體
空行之後就是可選的報文主體了,其中包含了所有型別的資料。請求主體中包括了要傳送個web伺服器的資料;響應主體中裝載了要返回給客戶端的資料。起始行和首部都是文字形式且都是結構化的,而主體則不同,主體可以包含任意的二進位制資料和文字。
*連線*
TCP/IP
HTTP是個應用層協議,聯網的細節都交給了TCP/IP協議。
TCP提供:
無差錯的資料傳輸;按序傳輸;未分段的資料流(可以在任意時刻以任意尺寸將資料傳送出去)
連線、IP地址及埠號
在HTTP客戶端向伺服器傳送報文之前,需要用網際協議(Internet Protocol,IP)地址和埠號在客戶端與伺服器之間建立一條TCP/IP 連線。
協議版本
HTTP/0.9
HTTP的1991原型版本。僅支援GET方法,不支援多媒體內容的MIME型別、各種HTTP首部,或者版本號。
HTTP/1.0
1.0是第一個得到廣泛使用的HTTP版本。HTTP/1.0添加了版本號、各種HTTP首部、一些額外的方法以及對多媒體物件的處理。
HTTP/1.0+
由很多流行的web客戶端和伺服器向HTTP中新增各種特性,包括keep-alive連線、虛擬主機支援、以及代理連線支援等,稱為非官方的事實標準。這種的HTTP擴充套件版本通常稱為HTTP/1.0+
HTTP/1.1
這個版本重點關注的是校正HTTP設計中的結構性缺陷,明確語義,引入重要的效能優化措施,並刪除一些不好的特性。它還包含了對20世紀90年代末正在發展中的更復雜的WEB應用程式和部署方式的支援。它也是當前使用的版本。
HTTP-NG(HTTP/2.0)
是HTTP/1.1後繼結構的原型建議,它重點關注的是效能的大幅優化以及更強大的服務邏輯遠端執行框架。它的研究工作終止於1998年。
*WEB的結構元件*
代理
代理位於客戶端和伺服器之間,接收所有客戶端的HTTP請求,並將這些請求轉發給伺服器(可能會對請求進行修改之後轉發)。
快取
WEB快取(cache)或代理快取是一種特殊的HTTP代理伺服器,可將經過代理傳送的常用文件複製儲存起來。下一個請求同一文件的客戶端就可以享受快取的私有副本所提供的服務了。
閘道器
閘道器(gateway)是一種特殊的伺服器,作為其他伺服器的中間實體使用。通常用於將HTTP流量轉換成其他的協議。閘道器接受請求時就好像自己是資源的源端伺服器一樣,客戶端可能並不知道自己在與一個閘道器進行通訊。
隧道
隧道(tunnel)是建立起來之後,就會在兩條連線之間對原始資料進行盲轉發的HTTP應用程式。通常用來在一條或多條HTTP連線上轉發非HTTP資料,轉發時不會窺探資料。
HTTP隧道一種常見用途是通過HTTP連線承載加密的安全套接字層(SSL,Secure Sockets Layer)流量。這樣SSL流量就可以穿過只允許WEB流量通過的防火牆了。
Agent代理
Agent代理是代表使用者發起HTTP請求的客戶端程式。所有釋出WEB請求的應用程式都是HTTP Agent代理。web瀏覽器。
第二章 URL與資源
瀏覽因特網資源
URL 可以通過HTTP之外的其他協議來訪問資源。它們可以指向因特網上的任意資源。比如個人郵箱賬戶。或者其他協議FTP、或者從流視訊伺服器下載電影
rtsp://www.xxxx.com:554/cto_video
URL的語法
大多數URL方案的URL語法都建立在這個由9部分構成的通用格式上:
://:@:/;?#
方案
實際上是規定如何訪問指定資源的主要識別符號,它會告訴負責解析URL的應用程式應該使用什麼協議。方案元件必須以一個字母符號開始,由第一個“:”符號將其與URL的其餘部分分隔開來,大小寫無關。
主機與埠
主機元件標識了因特網上能夠訪問資源的宿主機器。可以用主機名或者IP地址來表示。埠元件標識了伺服器正在監聽的網路埠。
使用者名稱和密碼
常見的如FTP伺服器需要使用者名稱和密碼才允許使用者訪問。
如果某應用程式使用的URL方案要求使用者輸入使用者名稱和密碼,比如FTP,但是使用者並未提供,它通常會插入一個預設的使用者名稱和密碼。比如FTP,會插入anonymous(匿名使用者)作為你的使用者名稱,併發送一個預設密碼(IE會發送IEUser,Netscapegoat Navigator則會發送mozilla)。
路徑
路徑元件說明了資源位於伺服器的什麼地方,路徑通常很像一個分級的檔案系統路徑。可以用“/”將HTTP URL 的路徑元件劃分成一些路徑段(path segment),每個路徑段都有自己的引數(param)元件。
引數
引數元件就是URL中的鍵值對列表,有字元“:”將其與URL的其他部分(以及各鍵值對)分隔開來,它們為應用程式提供了訪問資源所需的所有附加資訊。
ftp://prep.ai.mit.edu/pub/gnu;type=d
http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
查詢字串
比如資料庫服務,可以通過提問題或者進行查詢來縮小所請求資源類型範圍。
http://www.joes-hardware.com/inventory-check.cgi?item=12731
“?”右邊的內容稱為查詢元件,它和標識閘道器資源的URL路徑元件一起被髮送給閘道器資源,基本上可以將閘道器當做訪問其他應用程式的訪問點。
按照常規,很多閘道器都希望查詢字串以一系列“鍵/值”對的形式出現,鍵值對之間用“&”分隔。
片段
有些資源型別,比如HTML,除了資源級之外,還可以做進一步的劃分。比如一個帶章節的大型文字文件,資源的URL會指向整個文件,但是理想情況是能夠指向資源中那些章節。
為了引用部分資源或者資源的一部分,URL支援使用片段(frag)元件來表示一個資源內部的片段。比如:http://www.xxxx.com/tools.html#drills
HTTP伺服器通常只處理整個物件,而不是物件的片段,客戶端不能將片段傳送給伺服器。瀏覽器從伺服器獲取了整個資源後,會根據片段來顯示感興趣的那部分資源。
URL快捷方式
WEB客戶端可以理解並使用集中URL快捷方式。相對URL是在某資源內部指定一個資源的便捷縮略方式。很多瀏覽器還支援URL 的“自動擴充套件”。
相對URL
相對URL是不完整的,要從相對URL中獲取訪問資源所需的全部資訊,就必須相對於另一個,被稱為基礎的URL進行解析。相對URL是URL的一種便捷縮略記法。
上圖中的./hammers.html其實是個合法的相對URL,可以相對於它所在文件的URL對其進行解析,本例中就是/tools.html
相對URL只是URL的片段或是一小部分,處理URL的應用程式(瀏覽器)要能在兩者之間進行轉換。
需要注意,相對URL為保持一組資源的便攜性提供了一種便捷方式。如果使用相對URL,就可以在搬移一組文件的同時,仍然保持連結的有效性,因為相對URL是相對於新基礎進行解析的,這樣就能實現在其他伺服器上提供映象之類的功能了。
1、基礎URL
轉換處理的第一步就是找到基礎URL,基礎URL 作為參考點可以來自以下幾個不同的地方:
①在資源中顯示提供
有些資源會顯式的指定基礎URL,比如,HTML文件中可能包含一個定義了基礎 URL的HTML標記,通過它來轉換那個文件中所有的相對URL。
②封裝資源的基礎URL
如果在一個沒有顯式指定基礎URL的資源中發現了一個相對URL,如上例,可以將它所屬資源的URL作為基礎。
③沒有基礎URL
某些情況下,沒有基礎URL,這通常意味著你有一個相對URL,但有時可能只是一個不完整或損壞了的URL。
2、解析相對引用
要將相對URL轉換為一個絕對URL,下一步就是將相對URL和基礎URL劃分成元件段。
實際上,這樣只是在解析URL,但這種做法會將其劃分成一個個元件,因此通常會稱作分解(decomposing)URL。只要將基礎和相對URL劃分成了元件,就可以用如下的演算法完成轉換。
自動擴充套件URL
也就是常見的自動補全URL。
有兩種方式:
1、主機名擴充套件
在主機名擴充套件中,只要有些小提示,瀏覽器通常就可以在沒有幫助的情況下將你輸入的主機名擴充套件為完整的主機名。比如輸入yahoo,瀏覽器自動構建出www.yahoo.com
但是,這些主機名擴充套件技巧可能會為其他一些HTTP應用程式帶來問題,比如代理。
2、歷史擴充套件
將輸入的URL與歷史記錄中URL的字首進行匹配,並提供一些完整的選項。
各種令人頭疼的字元
URL是可移植的(portable)。
URL字符集
預設是US-ASCII字符集。有些URL會包含任意的二進位制資料。因此加入了轉義序列,通過轉義序列,就可用US-ASCII字符集的有限子集對任意字元值或資料進行編碼了。
編碼機制
轉義法—-包含一個百分號(%),後面跟兩個表示字元的ASCII碼的十六進位制數。
例如:
字元限制
在URL中,有幾個字元被保留起來有著特殊的含義。有些字元不在定義的US-ASCII可列印字符集中。還有些字元會與某些因特網閘道器和協議產生混淆,因此不贊成使用。
方案的世界
HTTP報文
HTTP報文是在HTTP應用程式之間傳送的資料塊。這些資料塊以一些文字形式的元資訊(meta-information)開頭,這些資訊描述了報文的內容以及含義。
HTTP使用術語流入(inbound)和流出(outbound)來描述事務處理(transaction)的方向。報文流入源端伺服器,工作完成後,會流回使用者的Agent代理中。如下圖:
報文的組成部分
HTTP報文是簡單的格式化資料塊。每條報文都包含一條來自客戶端的請求,或者一條來自伺服器的響應。由三個部分組成:對報文描述的起始行(start line)、包含屬性的首部(header)塊,以及可選的、包含資料的主體(body)部分。
起始行和首部就是由行分隔的ASCII文字。每行都以一個由兩個字元組成的行終止符作為結束,其中包括一個回車符和換行符。這個行終止序列可以寫作CRLF。報文的主體是一個可選的資料塊。與起始行和首部不同的是,主體中可以包含文字或二進位制資料,也可以為空。
報文的語法
所有的HTTP報文都可以分為:請求報文(request message)和響應報文(response message)。請求報文會向WEB伺服器請求一個動作。響應報文會將請求的結果返回給客戶端。
各部分的簡要描述:
1、方法(method)
客戶端希望伺服器對資源執行的動作,是一個單獨的單詞。
2、請求URL
命名了所請求的資源,或者URL路徑元件的完整URL。
3、版本
報文所使用的HTTP版本
HTTP/.
主要版本號 次要版本號 都是整數。
4、狀態碼
這三位數字描述了請求過程中所發生的情況。每個狀態碼的第一位數字都用於描述狀態的一般類別(成功、出錯等)
5、原因短語(reason-phrase)
數字狀態碼的可讀版本,包含行終止序列之前的所有文字。
6、首部
可以有零個或多個首部,每個首部都包含一個名字,後面跟著一個冒號(:),然後是一個可選的空格,接著是一個
值,最後是一個CRLF。首部是由一個空行(CRLF)結束的,表示了首部列表的結束和報文主體部分的開始。
7、實體的主體部分(entity-body)
這個部分包含一個由任意資料組成的資料塊。
起始行
1、請求行
請求報文請求伺服器對資源進行一些操作。請求報文的起始行或稱為請求行,包含了一個方法和一個請求URL,還包含
了HTTP的版本,用來告知伺服器,客戶端使用的是哪種HTTP。
2、響應行
響應報文承載了狀態資訊和操作產生的所有結果資料,將其返回個客戶端。它的起始行或稱為響應行,包含了響應報
文使用的HTTP版本、數字狀態碼、以及描述操作狀態的文字形式的原因短語。
3、方法
請求的起始行以方法作為開始,方法用來告知伺服器要做些什麼。
除了這些方法,其他伺服器可能還會實現一些自己的請求方法,這些附加的方法是對HTTP規範的擴充套件,因此被稱作擴
展方法。
4、狀態碼
狀態碼用來告知客戶端,發生了什麼事情。它位於響應的起始行中。通過三位數字程式碼對不同狀態碼進行分類。200
到299之間的狀態碼錶示成功,300到399之間的表示資源已經被移走。400到499之間的表示客戶端的請求出錯了。
500到599之間的表示伺服器出錯了。
5、原因短語
原因短語是響應起始行中的最後一個元件。它為狀態碼提供了文字形式的解釋。比如 HTTP/1.0 200 OK 中的OK 就是
原因短語。
6、版本號
使用版本號的目的是為使用HTTP的應用程式提供線索,以便互相瞭解對方的能力和報文格式。
首部
1、首部分類
通用首部–既可以出現在請求報文中,也可以出現在響應報文中。
請求首部
響應首部
實體首部–描述主體的長度和內容,或者資源自身。
擴充套件首部–規範中未定義的。
2、首部延續行
將長的首部行分為多行可以提高可讀性,多出來的每行前面至少要有一個空格或製表符(tab)
例如:
HTTP/1.0 200 OK
Content-Type: image/gif
Content-Length: 8572
Server: Test Server
Version 1.0
這個例子中,響應報文裡的server首部,其完整的值為: Test Server Version 1.0
版本0.9的報文
該報文也由請求和響應組成,但請求中只包含方法和請求URL,響應中只包含實體。他沒有版本資訊、狀態碼、原因短
語,也沒有首部。
方法
安全方法
HTTP定義了一組被稱為安全方法的方法。GET方法和HEAD方法都被認為是安全的。意味著使用GET和HEAD的HTTP請求都不會產生什麼動作。不產生動作就意味著HTTP請求不會在伺服器上產生什麼結果。
GET
用於請求伺服器傳送某個資源
HEAD
與GET類似,但伺服器在響應中只返回首部。不返回實體的主體部分。可以在不獲取資源的情況下了解資源的情況;通過檢視響應中的狀態碼,看看某個物件是否存在;測試資源是否被修改了。
PUT
向伺服器寫入文件,有些釋出系統允許使用者建立WEB頁面,並用PUT直接將其安裝的WEB伺服器上。
PUT方法的語義就是讓伺服器用請求的主體部分來建立一個由所請求的URL命名的新文件,如果那個URL存在的話,就用這個主體來替代它。
POST
該方法起初用來向伺服器輸入資料。實際上通常用來支援HTML的表單。
TRACE
客戶端發起一個請求時,這個請求可能要穿過防火牆、代理、閘道器或其他應用程式。每個中間節點都可能修改原始的HTTP請求。TRACE方法允許客戶端在最終請求傳送給伺服器時,看它變成了什麼樣子。 TRACE請求會在目的伺服器端發起一個”環回“診斷。行程最後一站的伺服器會彈回一條TRACE響應,並在響應主體中攜帶它收到的原始請求報文。
TRACE方法主要用於診斷—-用於驗證請求是否如願穿過了請求/響應鏈。可以檢視代理和其他應用程式對使用者請求所產生效果。 缺點:它假定中間應用程式對各種不同型別請求的處理是相同的。但很多HTTP應用程式會根據不同的方法做不同的事情,比如代理會將POST直接傳送給伺服器,而將GET傳送給另外一個HTTP應用程式(比如WEB快取)。但TRACE並不提供區分這些方法的機制。TRACE請求不能帶有實體的主體部分,響應的實體的主體部分是伺服器收到的請求的精確副本。
OPTIONS
該方法請求WEB伺服器告知其支援的各種功能。可以詢問伺服器通常支援哪些方法,或者對某些特殊資源支援哪些方法。
DELETE
請伺服器刪除請求URL所指定的資源,但是客戶端應用程式無法保證刪除操作一定會被執行。因為HTTP規範允許伺服器在不通知客戶端的情況下撤銷請求。
擴充套件方法
如果能夠在不破壞端到端行為的情況下將帶有未知方法的報文傳遞給下游伺服器的話,代理會嘗試著傳遞這些報文的,否則,它們會以501 Not Implemented(無法實現)狀態碼進行響應。
狀態碼
狀態碼為客戶端提供了一種理解事務處理結果的便捷方式。
100-199—-資訊性狀態碼
HTTP/1.1向協議中引入了資訊性狀態碼。這些狀態碼較新。
1、客戶端與100 Continue
如果客戶端在向伺服器傳送一個實體,且願意在傳送實體之前等待100 Continue響應,那麼客戶端就要傳送一個攜帶了值為100 Continue Expect 首部。傳送了值為100 Continue的Expect首部的客戶端不應該永遠等待伺服器傳送100 Continue響應。超過一段時間之後,客戶端應該直接將實體傳送出去。
2、伺服器與100 Continue
有些出錯的伺服器可能在沒有收到100 Continue的Expect首部的請求,也會發出響應碼。 出於某種原因,伺服器在傳送100 Continue 響應之前就收到了部分(或全部)實體,就說明客戶端已經決定繼續傳送資料了,這樣,伺服器就不需要在傳送這個狀態碼了。但是伺服器讀完請求之後,還是應該為請求傳送一個最終狀態碼(它可以跳過100 Continue狀態)。 如果伺服器收到了帶有100 Continue的請求,而且它決定在讀取實體的主體部分之前結束請求(比如因為出錯),就不應該僅僅是傳送一條響應並關閉連線,因為這樣會妨礙客戶端接收響應。
3、代理與100 Continue
代理收到該請求後,若它知道下一跳伺服器是HTTP/1.1相容的,或者並不知道下一跳伺服器與那個版本相容,都應該將Expect首部放在請求中向下轉發。如果它知道下一跳伺服器只能與HTTP/1.1之前的版本相容,就應該以417 Expectation Failed錯誤進行響應。(還有一種方法,就是想客戶端返回100 Continue ,向伺服器傳送時刪掉Expect首部)
200~299—-成功狀態碼
300~399—-重定向狀態碼
重定向狀態碼要麼告知客戶端使用替代位置來訪問他們所感興趣的資源,要麼就提供一個替代的響應而不是資源的內容。
可以通過某些重定向狀態碼對資源的應用程式本地副本與源端伺服器上的資源進行驗證。
當HTTP/1.0客戶端發起一個POST請求,並在響應中收到302狀態碼,它會接受Location首部的重定向URL,並向那個URL發起一個GET請求(而不是POST請求)。 在HTTP/1.1中使用303狀態碼來實現上述行為,為了避開這個問題,對於HTTP/1.1 客戶端,用307狀態碼取代302進行臨時重定向。這樣伺服器就可以將302儲存起來為HTTP/1.0客戶端使用了。
400~499—-客戶端錯誤狀態碼
500~599—-伺服器錯誤狀態碼
首部
五個主要的型別:
一、通用首部
比如Date首部,每一端都可以用它來說明構建報文的時間和日期:
Date: Tue, 3 Oct 1974 02:16:00 GMT
通用快取首部—HTTP/1.0引入了第一個允許HTTP應用程式快取物件本地副本的首部。
二、請求首部
請求報文特有,比如Accept首部用來告知伺服器客戶端會接受與其請求相符的任意媒體型別:
Accept: /
條件請求首部
安全請求首部
代理請求首部
三、響應首部
比如Server首部用來告知客戶端與哪一個版本的伺服器進行互動。
Server: TiKi-Hut/1.0
1、協商首部
資源有多種表示方法,比如某文件的法語和德語譯稿,HTTP/1.1可以為伺服器和客戶端提供對資源的協商能力。
2、安全響應首部
四、實體首部
比如可以用實體首部來說明實體主體部分的資料型別。通過下列Content-Type首部告知應用程式,資料是以iso-latin-
I 字符集表示的HTML文件。
Content-Type: text/html; charset=iso-latin-1
實體首部提供了有關實體及其內容的大量資訊,從有關物件型別的資訊,到能夠對資源使用的各種有效的請求方法。
1、內容首部—–提供了與實體內容有關的特定資訊,說明其型別、尺寸以及處理它所需的其他有用資訊。
2、實體快取首部—-提供了與被快取實體有關的資訊——比如,驗證已快取的資源副本是否仍然有效所需的資訊,以
及更好地估計已快取資源何時失效所需的線索。
五、擴充套件首部
非標準首部,由應用程式開發者建立,還未新增到已批准的HTTP規範中。即使不知道這些擴充套件首部的含義,HTTP程
序也要接受它們並轉發。
第四章 連線管理
一、TCP連線
4.1.1 TCP的可靠資料管道
HTTP連線實際上就是TCP連線和一些使用連線的規則。TCP為HTTP提供了一條可靠的位元傳輸管道。
4.1.2 TCP流是分段的、由IP分組傳送
TCP的資料是通過名為IP分組(或IP資料報)的小資料塊來發送的。這樣的話,如圖所示,HTTP就是協議棧的最頂層
了,其安全版本HTTPS就是在HTTP和TCP之間插入了一個(稱為TLS或者SSL的)密碼加密層。
4.1.3 保持TCP連線的正確執行
在任意時刻計算機都可以有幾條TCP連線處於開啟的狀態。TCP是通過埠號來保持這些連線的正確執行的。TCP連線
是通過4個值來識別的:
<源IP,源埠,目的IP,目的埠> 這4個值一起唯一確定一條連線。
4.1.4 用TCP套接字程式設計
4.2 對TCP效能的考慮
4.2.1 HTTP事務的時延
事務時延的主要原因:
1、 若之前未訪問過某主機,則需要DNS解析,花費數十秒。但大多數HTTP客戶端都有一個小的DNS快取,用來儲存
近期的IP地址。
2、 TCP連線建立大概一二秒,但如果有數百個HTTP事務,這個值會快速疊加。
3、 建立連線後,開始傳送HTTP請求,到達server 來處理的時延
4、 server回送HTTP響應報文時延
4.2.2 效能聚焦區域
TCP連線建立握手
TCP慢啟動擁塞控制
資料聚集的Nagle演算法
用於捎帶確認的TCP延遲確認演算法
TIME_WAIT時延的埠耗盡
4.2.3 TCP連線的握手時延
通常HTTP事務都不會交換太多資料。此時 SYN/SYN-ACK握手會產生一個可測量的時延。TCP連線的ACK分組通常足
夠大,可以承載整個HTTP請求報文。而且很多HTTP伺服器響應報文都可以放入一個IP分組中去(比如小型HTML檔案
或是對瀏覽器快取記憶體請求產生的304響應)。 這樣就會導致小的HTTP事務可能會在TCP建立上花費%50多的時間。
4.2.4 延遲確認
TCP的確認機制。確認報文很小,所以TCP允許在發往相同方向的輸出資料分組中對其進行”捎帶“。TCP將返回的確
認資訊與輸出的資料分組結合在一起,可以有效利用網路。
為了增加確認報文找到同向傳輸資料分組的可能性,很多TCP棧都實現了一種”延遲確認“演算法。該演算法會在一個特定
的視窗時間(100–200毫秒)內將輸出確認存放在緩衝區,以尋找能夠捎帶它的輸出資料分組,若沒有找到,則單獨
傳送。
但是,HTTP具有雙峰特徵的請求-應答行為降低了捎帶資訊的可能,所以延遲確認演算法會引入相當大的時延。
4.2.5 TCP慢啟動
TCP起初限制連線的最大速度,若資料傳輸成功,隨著時間推移提高傳輸速度。
慢啟動限制了一個TCP端點在任意時刻可以傳輸的分組數。每成功傳輸1個,傳送方就獲得了可以傳送2個的許可權。以
此類推,將會是4個,這樣的方式稱為”開啟擁塞視窗”。由於存在擁塞控制,新連線的傳輸速度就比已經交換過資料
的連線慢。
4.2.6 Nagle演算法與TCP_NODELAY
TCP有一個數據流介面,應用程式可以通過它將任意大小的資料放入TCP棧中——即使一次放一個位元組。但是每個TCP
段中都至裝載了40個位元組的標記和首部,這樣大量的包含少資料的分組就會影響網路效能。
Nagle演算法試圖在傳送一個分組之前,將大量的TCP資料繫結在一起,提高網路效率。 RFC 896
該演算法鼓勵傳送全尺寸(LAN上為約1500位元組,因特網上是幾百位元組)的段。只有當所有其他分組都被確認後,此算
法才允許傳送非全尺寸的分組。若其他分組仍在傳輸中,就將那部分資料快取起來。只有當掛起分組被確認,或者緩
存中積累了足夠傳送一個全尺寸分組的資料時,才會將快取資料傳送出去。
該演算法會引發幾種HTTP效能問題,首先,小的HTTP報文可能無法填滿一個分組,可能會因為等待那些永遠不會到來
的額外資料而產生延遲。其次,Nagle演算法與延遲確認之間的互動存在問題——Nagle演算法會阻止資料的傳送,直到有
確認分組抵達為止,但是確認分組本身會被延遲確認演算法延遲100~200毫秒。
HTTP應用程式通常會在自己的棧中設定引數TCP_NODELAY禁用此演算法。但這樣就要確保向TCP寫入大塊資料。
4.2.7 TIME_WAIT累積與埠耗盡
當TCP端點關閉TCP連線時,會在記憶體中維護一個小的控制塊,用來記錄最近所關閉連線的IP地址和埠號。通常維持
是所估計的最大分段使用期的兩倍左右(2MSL,通常為2分鐘),以確保在這段時間內不會建立具有相同地址和埠
的連線。
2MSL的連線關閉延遲通常不是問題。但在效能基準環境下,通常只有一臺或幾臺用來產生流量的計算機連線到某系統
中去,這樣就限制了連線到伺服器的客戶端IP地址數。而且,伺服器通常會在HTTP的預設80埠監聽。用
TIME_WAIT防止埠號重用時,這些情況也限制了可用的連線值組合。
在只有一個伺服器一個客戶端情況下,client每次連到server上都有一個新的源埠,實現連線的唯一性,但源埠數
量有限,且在2MSL秒(120s)內無法重用,這樣連線率就限制在了500次/秒。若再進行優化,且server的連線率不
高於500次/秒,就能確保不會遇到TIME_WAIT埠耗盡問題。要修正此問題,可以增加client負載生產機器的數量,
或者確保client和server在迴圈使用幾個虛擬IP。
即使沒有遇到埠耗盡問題,也要特別小心有大量連線處於開啟狀態的情況,或者為處於等待狀態的連線分配了大量
控制塊的情況。
4.3 HTTP連線的處理
4.3.1 常被誤解的Connection首部
HTTP允許在客戶端和最終的源端伺服器之間存在一串HTTP中間實體(代理、快取記憶體等)。在某些情況下,兩個相
鄰的HTTP應用程式會為它們共享的連線應用一組選項。HTTP的Connection首部欄位中有一個由逗號分隔的連線標籤
列表,這些標籤為此連線指定了一些不會傳播到其他連線中去的選項。比如,可以用Connection:close 來說明發送
完下一條報文之後必須關閉的連線。
Connection首部可以承載3中不同型別的標籤:
HTTP首部欄位名,列出只與此連線有關的首部
任意標籤值,用於描述此連線的非標準選項
值close,說明操作完成後需關閉這條持久連線
如果連線標籤中包含了一個HTTP首部欄位的名稱,那麼這個首部欄位就包含了與一些連線有關的資訊,不能將其轉發
出去。在將報文轉發出去之前,必須刪除Connection首部列出的所有首部欄位。由於Connection首部可以防止無意
中對本地首部的轉發,因此將逐跳首部名放入Connection首部被稱為“對首部的保護”。
HTTP應用程式收到一條帶有Connection首部的報文時,接收端會解析傳送端請求的所有選項,並應用。然後會在將
此報文轉發給下一跳地址之前,刪除Connection首部以及Connection中列出的所有首部。而且還會有少量沒有作為
Connection首部值列出,但一定不能被代理轉發的逐條首部。其中包括Proxy-Authenticate/Proxy-
Connection/Transfer-Encoding/Upgrade.
4.3.2 序列事務處理時延
連線時延和慢啟動時延會因為序列疊加起來。
序列載入另一缺點,有些瀏覽器在物件載入完畢之前無法獲知物件的尺寸,而且它們可能需要尺寸資訊來決定將物件
放在螢幕的什麼位置,所以在載入足夠多物件前,無法在螢幕上顯示任何內容。
有幾種新的方法可以提高HTTP連線效能:
並行連線—-通過多條TCP連線發起併發的HTTP請求
持久連線—-重用TCP連線,以消除連線以及關閉時延
管道化連線—-通過共享的TCP連線發起併發的HTTP請求
複用的連線—-交替傳送請求和響應報文(實驗階段)
4.4 並行連線
4.4.1 並行連線可能會提高頁面的載入速度
包含嵌入物件的組合頁面如果能通過並行連線克服單條連線的空載時間和頻寬限制,載入速度也會有所提高。時延
可以重疊起來,而且如果單條連線沒有充分利用客戶端頻寬,可以將未用頻寬分配來裝載其他物件。
4.4.2 並行未必更快
客戶端網路頻寬不足時(比如,瀏覽器是通過一個28.8Kbps的Modem連線到因特網上去),大部分的時間可能
都是用來傳輸資料。這樣,一個連線到速度較快的伺服器的HTTP事務就會很容易耗盡所有可用Modem頻寬。如果
並行載入多個物件時,每個物件都去競爭這有限的頻寬,每個物件都會以較慢的速度按比例載入,這樣帶來的效能
提升就很小,甚至沒有。
實際上,瀏覽器確實使用了並行連線,但是會將連線的總數限制在一個較小的值(通常是4個)。伺服器可以隨意關
閉來自特定客戶端的超量連線。
4.5 持久連線
WEB客戶端經常會開啟到同一個站點的連線。比如,一個WEB頁面上的大部分內嵌圖片通常來自同一個WEB站點,而
且相當一部分指向其他物件的超連結都是指向同一個站點。因此,初始化了對某伺服器的應用程式很可能在不久的將
來對那臺伺服器發起更多的請求。這種性質被稱為站點本地性。
因此,HTTP/1.1允許HTTP裝置在事務處理結束之後將TCP連線保持在開啟狀態,以便為未來的HTTP請求重用現存的
連線。持久連線會在不同事務之間保持開啟狀態,直到客戶端或者伺服器決定將其關閉。
4.5.1 持久及並行連線
並行連線可以提高複合頁面的傳輸速度。但也有一些缺點:
1、每個事務都會開啟/關閉一條新的連線、會耗費時間和頻寬
2、由於TCP慢啟動特性,每條新連線的效能都會有所降低
3、可開啟的並行連線數量有限
持久連線比並行連線更好在降低了時延和建立連線的開銷。但是管理持久連線需要特別小心。
4.5.2 HTTP/1.0+keep-alive連線
4.5.3 Keep-Alive操作
實現HTTP/1.0 keep-alive連線的客戶端可以通過包含 Connection: Keep-Alive首部請求將一條連線保持在開啟
狀態。
如果伺服器願意為下一條請求將連線保持在開啟狀態,就在響應中包含相同的首部。如果響應中沒有 Connection:
Keep-Alive 首部,客戶端就會認為伺服器不支援keep-alive,會在響應報文之後關閉連線。
4.5.4 Keep-Alive選項
keep-alive首部只是請求將連線保持在活躍狀態。發出keep-alive請求之後,客戶端和伺服器並不一定同意進行
keep-alive會話。它們可以在任意時刻關閉空閒的keep-alive連線,並可隨意限制keep-alive連線所處理事務數量
可以用keep-alive通用首部中指定的、由逗號分隔的選項來調節行為:
1、timeout是在keepalive響應首部發送的。它估計了伺服器希望將連線保持在活躍狀態的時間。並非承諾值
2、max也是在響應首部發送的。估計了伺服器還希望為多少個事務保持此連線的活躍狀態,並非承諾值。
3、keep-alive首部還可以支援任意未經處理的屬性,這些屬性主要用於診斷除錯。語法:name [=value]
4.5.5 keep-alive連線的限制和規則
*HTTP/1.0中,並非預設使用,客戶端需傳送一個請求首部來啟用keep-alive連線
*請求首部必須隨所有希望保持持久連線的報文一起傳送
*如果此響應中沒有Connection: Keep-Alive響應首部,就可以知道伺服器發出響應後是否會關閉連線了
*代理和閘道器必須執行Connection首部的規則。代理或閘道器必須在將報文轉發出去或將其快取記憶體之前,刪除在
Connection首部中命名的所有首部欄位以及首部自身。
*嚴格來說,不該與無法確定是否支援Connection首部的代理伺服器建立keep-alive連線
*除非重複傳送請求會產生其他一些副作用,否則如果在客戶端收到完整的響應之前連線就關閉了,客戶端就一定要
做好重試請求的準備。
4.5.6 Keep-Alive和啞代理
WEB客戶端的Connection: keep-alive首部應該只會對這條離開客戶端的
TCP鏈路產生影響。
1、Connection首部和盲中繼
問題出在代理上—-尤其是那些不理解Connection首部,而且不知道在沿
著轉發鏈路將其傳送出去之前,應該將該首部刪除的代理。很多老的或簡
單的代理都是盲中繼(blind relay),它們只是將位元組從一個連線轉發到
另一個連線中去,不對Connection首部進行特殊處理。
2、代理和逐跳首部
為避免此類代理通訊問題,現代的代理都決不能轉發Connection首部和
所有名字出現在Connection值中的首部。另外,還有幾個不能作為
Connection首部值列出,也不能被代理轉發或作為快取響應使用的首
部。其中包括:Proxy-Authenticate/Proxy-Connection/Transfer-
Encoding/Upgrade.
4.5.7 插入Proxy-Connection
Netscape的做法是,瀏覽器向代理髮送非標準的Proxy-Connection擴充套件首
部,而不是官方的Connection首部。如果代理是盲中繼,會將無意義的
Proxy-Connection首部轉發給伺服器,而伺服器會忽略此首部。但如果是一
個能夠理解持久連線的代理,就會用一個Connection首部代替這個首部,將
其傳送給伺服器。
在客戶端和伺服器之間只有一個代理時,可以使用這種方案來解決問題,但
是,一旦在啞代理的任意一側還有一個聰明的代理,問題就會再次發生。
4.5.8 HTTP/1.1 持久連線
HTTP/1.1 逐漸停止了對keep-alive的支援,用一種名為持久連線
(persistent connection)的改進型設計取代。
HTTP/1.1 持久連線在預設情況下是啟用的,除非特別指明,否則,HTTP/1.1
假定所有的連線都是持久的。要在事務結束之後將連線關閉,HTTP/1.1應用
程式必須向報文中顯式地新增一個Connection: close首部。但是,客戶端
和伺服器仍然可以隨時關閉空閒連線,不傳送close並不意味著伺服器承諾永
遠將連線保持在開啟狀態。
4.5.9 持久連線的限制和規則
*傳送了Connection: close請求首部後,客戶端就無法在那條連線上傳送更
多的請求了。
*若客戶端不想在連線上傳送其他請求了,就應該在最後一個請求中傳送close
*只有當連線上所有的報文都有正確的、自定義報文長度時(也就是說,實體
部分的長度和相應的Content-Length一致,或者是用分塊傳輸編碼方式編碼
的)—–連線才能持久保持
*HTTP/1.1的代理必須能分別管理與客戶端和伺服器的持久連線—-每個持久
連線都只適用於一跳傳輸
*由於較老的代理會轉發Connection首部,所以,HTTP/1.1的代理伺服器不
應與HTTP/1.0客戶端建立持久連線。
*儘管伺服器不該在傳輸報文的過程中關閉連線,而且在關閉連線之前至少應
該響應一條請求。但不管Connection首部取什麼值,HTTP/1.1裝置都可在
任意時刻關閉連線。
*HTTP/1.1 應用程式必須能從非同步的關閉中恢復出來,只要不存在可能會累積
起來的副作用,客戶端都應該重試這條請求。
*除非重複發起請求會產生副作用,否則如果在客戶端收到整條響應之前連線
關閉了,客戶端都必須要重新發起請求。
*一個使用者客戶端對任何伺服器或代理最多隻能維護兩條持久連線,以防止服
務器過載。代理可能需要更多到伺服器的連線來支援併發使用者的通訊,所以,
如果有N個使用者試圖訪問伺服器,代理最多要維持2N條到任意伺服器或父代
理的連線。
4.6 管道化連線
在響應到達之前,可以將多條請求放入佇列。當第一條請求通過網路流向另一端
的伺服器時,第二條和第三條請求也可以開始傳送了。這樣可以降低網路的環回
時間,提高效能。
對管道化連線有幾條限制:
!如果HTTP客戶端無法確認連線是持久的,就不該使用管道
!必須按照與請求相同的順序回送HTTP響應。HTTP報文中沒有序列號標籤,
因此如果收到的響應失序了,就無法進行匹配
!HTTP客戶端必須做好連線會在任意時刻關閉的準備,還要準備好重發所有
未完成的管道化請求
!HTTP客戶端不應該用管道化的方式傳送會產生副作用的請求(如POST)。總
之,出錯的時候,管道化方式會阻礙客戶端了解伺服器執行的是一系列管道
化請求中的哪一些。由於無法安全的重試POST這樣的非冪等請求,所以出
錯時,就存在某些方法永遠不會被執行的風險。