HTTP相關
- 2021 年 5 月 22 日
- 筆記
HTTP
什麼是HTTP?
HTTP 是超文本傳輸協議,也就是HyperText Transfer Protocol。
詳細解釋
HTTP 是一個在電腦世界裡專門在「兩點」之間「傳輸」文字、圖片、音頻、影片等「超文本」數據的「約定和規範」。
什麼是socket
套接字,TCP/IP網路的API。Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面.
Socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層複雜的操作抽象為幾個簡單的介面供應用層調用已實現進程在網路中通訊。
HTTP和Socket的關係
客戶端的套接字介面是客戶進程與TCP連接之間的門,在伺服器端的套接字介面則是伺服器進程與TCP連接之間的門.
客戶端向他的套接字介面發送HTTP請求報文並從它的套接字介面接收HTTP響應報文,類似的,伺服器從它的套接字介面接收HTTP請求報文和向它的套接字介面發送HTTP響應報文.一旦客戶向它的套接字介面發送了一個請求報文,該報文就脫離了客戶控制並進入TCP的控制.
HTTP的特點
- HTTP是一個無狀態協議.即伺服器向客戶發送被請求的文件,而不存儲任何關於該客戶的狀態資訊.
無狀態的好處與壞處
-
無狀態的好處,因為伺服器不會去記憶 HTTP 的狀態,所以不需要額外的資源來記錄狀態資訊,這能減輕伺服器的負擔,能夠把更多的 CPU 和記憶體用來對外提供服務。
-
無狀態的壞處,既然伺服器沒有記憶能力,它在完成有關聯性的操作時會非常麻煩。
例如登錄->添加購物車->下單->結算->支付,這系列操作都要知道用戶的身份才行。但伺服器不知道這些請求是有關聯的,每次都要問一遍身份資訊。
Cookie進行狀態管理
對於無狀態的問題,解法方案有很多種,其中比較簡單的方式用 Cookie 技術。
Cookie
通過在請求和響應報文中寫入 Cookie 資訊來控制客戶端的狀態。
-
沒有Cookie資訊狀態下的請求
-
第2次以後(存有Cookie資訊狀態)的請求
發生Cookie交互的情景中,HTTP請求報文和響應報文的內容如下.
-
請求報文(沒有Cookie資訊的狀態)
-
響應報文(伺服器端生成Cookie資訊)
-
請求報文(自動發送保存著的Cookie資訊)
HTTP報文格式
-
HTTP請求報文
如下是一個HTTP請求報文
請求報文的第一行叫做請求行,其後繼的行叫做首部行,請求行有3個欄位:方法欄位,URL欄位和HTTP版本欄位,方法欄位可以取不同的值,包括GET,POST,HEAD,PUT和DELETE.
在本例中,該瀏覽器正在向 /chapter17/user.html 提交表單,實現的是HTTP/1.1協議
User-Agent:
向伺服器發送請求的瀏覽器類型Connection: Keep-Alive
: 使用持續連接Host:
指明對象所在的主機Cookie:
類型為「小型文本文件」,是某些網站為了辨別用戶身份,進行Session跟蹤而儲存在用戶本地終端上的數據(通常經過加密),由用戶客戶端電腦暫時或永久保存的資訊一個HTTP請求報文的通用格式如下
-
HTTP響應報文
如下是一個HTTP響應報文
它有三個部分:響應行,首部行,實體體(entity body)
實體體部分是報文的主要部分,包含了所請求的對象本身.
響應行有3個欄位:協議版本欄位,狀態碼和相應狀態資訊.
在這個例子中,狀態行指示伺服器正在使用HTTP/1.1,並且一切正常
Date:
伺服器產生並發送該響應報文的日期和時間.(不是指對象創建或者最後修改的時間,而是伺服器從它的文件系統中檢索到該對象,將該對象插入響應報文,並發送該響應報文的時間)Server:
指示該報文是由一台Apache-Coyote/1.1伺服器產生的Content-Type:
指示了實體體中的對象是json文本一個HTTP響應報文的通用格式如下
HTTP的請求方法
常見的狀態碼
200 OK:
請求成功,資訊在返回的響應報文中
301 Moved Permanently:
請求的對象已經被永久轉移,新的URL定義在響應報文的Location:首部行中.客戶軟體將自動獲取新的URL.
例如,當lldexample更名為example時,他們將URL從lldexample.com更改為example.com,每個lldexample.com頁面都通過永久的301重定向重定向到相應的example.com頁面。
302 Found:
臨時重定向,表示請求的資源已被分配了新的URI,希望用戶(本次)能使用新的URI訪問.
例如,可以在登陸用戶訪問用戶中心的時候重定向到登錄頁面。接著,搜索引擎就會獲取新內容,並保留舊的URL。由於伺服器返回的是302程式碼,搜索引擎會認為新的網址只是暫時的。
400 Bad Request:
表示請求報文中存在語法錯誤.當錯誤發生時,需修改請求的內容後再次發送請求.
403 Forbidden:
表示對請求資源的訪問被伺服器拒絕了.
404 Not Found:
表示伺服器上無法找到請求的資源
什麼情況下會出現404?
> 第一種:
用戶輸入的地址鏈接有誤,導致IIS提示404 not found。
> 第二種:
伺服器上本該有的頁面已經被刪除了,這種情況多發於BBS論壇,N年前的帖子如今被你通過搜索引擎搜索出來了,但實際上BBS論壇為了保障伺服器的資源合理運用,都會將過期或非常久遠的資訊頁面刪除,導致404 not found。
> 第三種:
DNS設置阻止,就中文環境而言,國外有一些被禁網站在中國瀏覽同樣會出現404 not found的現象,這需要使用代理伺服器才可以正常瀏覽。
500 Internal Server Error:
表示伺服器在執行請求時發生了錯誤,也可能是web應用存在bug或臨時故障
503 Service Unavaliable:
表示伺服器暫時處於超負載或正在進行停機維護,現在無法處理請求
505 HTTP Version Not Supported:
伺服器不支援請求報文使用的HTTP協議版本
HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/3 演變
-
HTTP/1.0:
1996年5月,HTTP/1.0 版本發布,內容大大增加。首先,任何格式的內容都可以發送。這使得互聯網不僅可以傳輸文字,還能傳輸影像、影片、二進位文件(超文本)。這為互聯網的大發展奠定了基礎。
其次,除了
GET
命令,還引入了POST
命令和HEAD
命令,豐富了瀏覽器與伺服器的互動手段。再次,HTTP請求和回應的格式也變了。除了數據部分,每次通訊都必須包括頭資訊(HTTP header),用來描述一些元數據。
其他的新增功能還包括狀態碼(status code)、多字符集支援、多部分發送(multi-part type)、許可權(authorization)、快取(cache)、內容編碼(content encoding)等。
痛點:每個TCP連接只能發送一個請求,發送數據完畢,鏈接就關閉,如果還要請求其他資源,就必須再新建一個連接。
TCP連接的新建成本很高,因為需要客戶端和伺服器三次握手,並且開始時發送速率較慢(slow start)。所以,HTTP 1.0版本的性能比較差。隨著網頁載入的外部資源越來越多,這個問題就愈發突出了。
-
HTTP/1.1:
1997年1月,HTTP/1.1 版本發布,只比 1.0 版本晚了半年。它進一步完善了 HTTP 協議,一直用到了20年後的今天,直到現在還是最流行的版本。為了解決HTTP 1.0的這個痛點,HTTP/1.1支援持續連接(HTTP/1.1的默認模式使用帶流水線[1]的持久連接),在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲。一個包含有許多影像的網頁文件的多個請求和應答可以在一個連接中傳輸,但每個單獨的網頁文件的請求和應答仍然需要使用各自的連接。
管道機制:HTTP 1.1還允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但伺服器端必須按照接收到客戶端請求的先後順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容,這樣也顯著地減少了整個下載過程所需要的時間。
痛點:
- 雖然1.1版允許復用TCP連接,但是同一個TCP連接裡面,所有的數據通訊是按次序進行的。伺服器只有處理完一個回應,才會進行下一個回應。也就是如果一個響應返回延遲了,那麼其後續的響應都會被延遲,直到隊頭的響應送達。
- 單向請求,只能由客戶端發起。
- 請求報文與響應報文首部資訊冗餘量大。
- 數據未壓縮,導致數據的傳輸量大
-
HTTP/2:
2015年,HTTP/2 發布。它不叫 HTTP/2.0,是因為標準委員會不打算再發布子版本了,下一個新版本將是 HTTP/3。二進位分幀
HTTP/1.1 版的頭資訊肯定是文本(ASCII編碼),數據體可以是文本,也可以是二進位。HTTP/2 則是一個徹底的二進位協議,頭資訊和數據體都是二進位,並且統稱為”幀”(frame):頭資訊幀和數據幀。
多路復用
下面是幾個概念:
- 流(
stream
):已建立連接上的雙向位元組流。 - 消息:與邏輯消息對應的完整的一系列數據幀。
- 幀(
frame
):HTTP/2
通訊的最小單位,每個幀包含幀頭部,至少也會標識出當前幀所屬的流(stream id
)。
從圖中可見,所有的
HTTP/2
通訊都在一個TCP
連接上完成,這個連接可以承載任意數量的雙向數據流。每個數據流以消息的形式發送,而消息由一或多個幀組成。這些幀可以亂序發送,然後再根據每個幀頭部的流標識符(
stream id
)重新組裝。另外,多路復用(連接共享)可能會導致關鍵請求被阻塞。
HTTP/2
里每個數據流都可以設置優先順序和依賴,優先順序高的數據流會被伺服器優先處理和返回給客戶端,數據流還可以依賴其他的子數據流。可見,
HTTP/2
實現了真正的並行傳輸,它能夠在一個TCP
上進行任意數量HTTP
請求。而這個強大的功能則是基於「二進位分幀」的特性。頭部資訊壓縮
HTTP 協議不帶有狀態,每次請求都必須附上所有資訊。所以,請求的很多欄位都是重複的,比如
Cookie
和User Agent
,一模一樣的內容,每次請求都必須附帶,這會浪費很多頻寬,也影響速度。HTTP/2 對這一點做了優化,引入了頭資訊壓縮機制(header compression)。一方面,頭資訊使用
gzip
或compress
壓縮後再發送;另一方面,客戶端和伺服器同時維護一張頭資訊表,所有欄位都會存入這個表,生成一個索引號,以後就不發送同樣欄位了,只發送索引號,這樣就提高速度了。伺服器推送
HTTP/2 允許伺服器未經請求,主動向客戶端發送資源,這叫做伺服器推送(server push)。
常見場景是客戶端請求一個網頁,這個網頁裡面包含很多靜態資源。正常情況下,客戶端必須收到網頁後,解析HTML源碼,發現有靜態資源,再發出靜態資源請求。其實,伺服器可以預期到客戶端請求網頁後,很可能會再請求靜態資源,所以就主動把這些靜態資源隨著網頁一起發給客戶端了。
痛點:
- 建立連接時間長(本質上是TCP的問題)隊頭阻塞問題移動互聯網領域表現不佳(弱網環境)
- 移動互聯網領域表現不佳
- TCP隊頭阻塞問題
- 流(
-
HTTP/3:
在我們眼裡,TCP是面向連接、可靠的傳輸層協議,當前幾乎所有重要的協議和應用都是基於TCP來實現的。網路環境的改變速度很快,但是TCP協議相對緩慢,正是這種矛盾促使Google做出了一個看似出乎意料的決定-基於UDP來開發新一代HTTP協議。
Google決定在UDP基礎上改造一個具備TCP協議優點的新協議也就順理成章了,這個新協議就是QUIC[2]協議。
在設計之初,Google就希望使用這個協議來取代HTTPS/HTTP協議,使網頁傳輸速度加快。2015年6月,QUIC的網路草案被正式提交至互聯網工程任務組。2018 年 10 月,互聯網工程任務組 HTTP 及 QUIC 工作小組正式將基於 QUIC 協議的 HTTP(英語:HTTP over QUIC)重命名為HTTP/3。
所以,我們現在所提到的HTTP/3,其實就是HTTP over QUIC,即基於QUIC協議實現的HTTP。
QUIC協議必須要實現HTTP2.0在TCP協議上的重要功能,同時解決遺留問題,我們來看看QUIC是如何實現的。
隊頭阻塞問題
回顧:
所有的數據通訊是按次序進行的。伺服器只有處理完一個回應,才會進行下一個回應。也就是如果一個響應返回延遲了,那麼其後續的響應都會被延遲,直到隊頭的響應送達。在
HTTP/2
協議中的多路復用機制解決了HTTP層的隊頭阻塞問題,但是在TCP層仍然存在隊頭阻塞問題.TCP協議在收到數據包之後,這部分數據可能是亂序到達的,但是TCP必須將所有數據收集排序整合後給上層使用,如果其中某個包丟失了,就必須等待重傳,從而出現某個丟包數據阻塞整個連接的數據使用。
但是,QUIC協議是基於UDP協議實現的,在一條鏈接上可以有多個流,流與流之間是互不影響的,當一個流出現丟包影響範圍非常小,從而解決隊頭阻塞問題。
建鏈時間長問題
衡量網路建鏈的常用指標是RTT Round-Trip Time,也就是數據包一來一回的時間消耗。
一般來說HTTPS協議要建立完整鏈接包括:TCP握手和TLS握手,總計需要至少2-3個RTT,普通的HTTP協議也需要至少1個RTT才可以完成握手。
然而,
QUIC協議
可以實現在第一個包就可以包含有效的應用數據,從而實現0RTT這在連接時延上有很大優勢,可以節約數百毫秒的時間
但是對於雙方完全陌生的情況下,為了保證傳輸的安全,我們需要進行一次連接
使用QUIC協議的客戶端和服務端要使用1RTT進行密鑰協商,使用的密鑰協商演算法是
DH(Diffie-Hellman)迪菲-赫爾曼演算法
。當密鑰協商完之後,客戶端會存儲服務端發送來的config包,後續再連接時可以直接使用,從而跳過這個1RTT,實現0RTT的業務數據交互.
但是客戶端保存config是有時間期限的,在config失效之後仍然需要進行首次連接時的密鑰交換。
移動互聯網領域表現不佳問題
網路切換幾乎無時無刻不在發生。
TCP協議使用五元組來表示一條唯一的連接,當我們從4G環境切換到wifi環境時,手機的IP地址就會發生變化,這時必須創建新的TCP連接才能繼續傳輸數據。
QUIC協議基於UDP實現摒棄了五元組的概念,使用64位的隨機數作為連接的ID,並使用該ID表示連接。
基於QUIC協議之下,我們在日常wifi和4G切換時,或者不同基地台之間切換都不會重連,從而提高業務層的體驗。
UDP鏈接的安全問題
通俗來說,前向安全指的是密鑰泄漏也不會讓之前加密的數據被泄漏,影響的只有當前,對之前的數據無影響。
前面提到QUIC協議首次連接時先後生成了兩個加密密鑰,由於config被客戶端存儲了,如果期間服務端私鑰泄漏,那麼可以根據K = mod p計算出密鑰K。
如果一直使用這個密鑰進行加解密,那麼就可以用K解密所有歷史消息,因此後續又生成了新密鑰,使用其進行加解密,當時完成交互時則銷毀,從而實現了前向安全。
丟包處理
FEC前向糾錯
QUIC協議的每個數據包除了本身的數據以外,會帶有其他數據包的部分數據,在少量丟包的情況下,可以使用其他數據包的冗餘數據完成數據組裝而無需重傳,從而提高數據的傳輸速度。具體實現類似於RAID5,將N個包的校驗和(異或)建立一個單獨的數據包發送,這樣如果在這N個包中丟了一個包可以直接恢復出來。除此之外還可以用來校驗包的正確性(已廢棄)關鍵包發送多次
同時,對於一些非常重要的包,QUIC在發送後的短時間內如果沒收到回包,便會重發請求,以確保重要的節點不被Delay
DNS協議
DNS(Domain Name System)服務是和HTTP協議一樣位於應用層的協議.它提供域名到IP地址之間的解析服務
電腦既可以被賦予IP地址,也可以被賦予主機名和域名.比如 www.baidu.com.
用戶通常使用主機名或域名來訪問對方的電腦,而不是直接通過IP地址訪問.因為與IP地址的一組純數字相比,用字母配合數字的表示形式來指定電腦名更符合人類的記憶習慣
DNS協議提供通過域名查找IP地址,或逆向從IP地址反向查域名的服務
獲得www.baidu.com的IP地址的做法如下:
- 同一台用戶主機上運行著DNS應用的客戶端
- 瀏覽器從URL中抽取出主機名www.baidu.com,並將這台主機名傳給DNS應用的客戶端
- DNS客戶向DNS伺服器發送一個包含主機名的請求
- DNS客戶最後會收到一份回答報文,其中含有對應於該主機名的IP地址.
- 一旦瀏覽器接收到來自DNS的該IP地址,它能夠向位於該IP地址80埠的HTTP伺服器進程發起一個TCP連接
通過DNS伺服器查詢IP地址的過程如下:
-
根DNS伺服器:
有400多個根名字伺服器遍及全世界.這些根名字伺服器由13個不同組織管理 -
頂級域伺服器:
對於每個頂級域(如com,org,net,edu和gov)和所有的國家的頂級域(如uk,fr,ca和jp),都有TLD伺服器(或伺服器集群 -
本地伺服器:
嚴格來說,一個本地DNS伺服器並不屬於該伺服器的層次結構,但它對DNS層次結構是至關重要的.每個ISP都有一台本地DNS伺服器(也叫默認名字伺服器).當主機與某個ISP連接時,該ISP提供一台主機的IP地址,該主機具有一台或多台其本地DNS伺服器的IP地址(通常通過DHCP) -
DNS快取:
為了改善時延性能並減少在網際網路上到處傳輸的DNS報文數量,DNS廣泛運用了快取技術.原理是,在一個請求鏈中,當某DNS伺服器接受一個DNS回答時,它能將映射快取在本地存儲器中.
HTTPS
HTTP與HTTPS的區別
- HTTP 是超文本傳輸協議,資訊是明文傳輸,存在安全風險的問題。HTTPS 則解決 HTTP 不安全 的缺陷,在 TCP 和 HTTP 網路層之間加入了 SSL/TLS 安全協議,使得報文能夠加密傳輸。
- HTTP 連接建立相對簡單, TCP 三次握手之後便可進行 HTTP 的報文傳輸。而 HTTPS 在 TCP 三次握手之後,還需進行 SSL/TLS 的握手過程,才可進入加密報文傳輸。
- HTTP 的埠號是 80,HTTPS 的埠號是 443。
- HTTPS 協議需要向 CA(證書權威機構)申請數字證書,來保證伺服器的身份是可信的。
HTTP的痛點
- 竊聽風險,比如通訊鏈路上可以獲取通訊內容,用戶號容易沒。
- 篡改風險,比如強制植入垃圾廣告,視覺污染,用戶眼容易瞎。
- 冒充風險,比如冒充淘寶網站,用戶錢容易沒。
HTTPS如何解決這些問題?
HTTPS 在 HTTP 與 TCP 層之間加入了 SSL/TLS
協議,可以很好的解決了上述的風險:
- 資訊加密:交互資訊無法被竊取,但你的號會因為「自身忘記」帳號而沒。
- 校驗機制:無法篡改通訊內容,篡改了就不能正常顯示,但百度「競價排名」依然可以搜索垃圾 廣告。
- 身份證書:證明淘寶是真的淘寶網,但你的錢還是會因為「剁手」而沒。
資訊加密的三種方式
-
對稱加密:
加密和解密同用一個密鑰的方式稱為共享密鑰加密,也被叫做對稱密鑰加密.常用的對稱加密演算法有DES,AES加密
問題是如何安全的轉交密鑰到對方手中呢?
-
非對稱加密:
非對稱加密演算法需要兩個密鑰:公開密鑰(publickey:簡稱公鑰)和私有密鑰(privatekey:簡稱私鑰)。公鑰與私鑰是一對,如果用公鑰對數據進行加密,只有用對應的私鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種演算法叫作非對稱加密演算法。常用的對稱加密演算法有RSA加密.
值得注意的是,RSA所要求的指數運算相當耗費時間,形成對比的是,DES用軟體實現要比RSA快100倍,所以,在實際應用中,RSA通常與對稱密鑰密碼結合起來使用
-
Hash:
hash 是把任意長度數據經過處理變成一個長度固定唯一的字元串,但任何人拿到這個字元串無法反向解密成原始數據(解開你就是密碼學專家了),Hash 常用來驗證數據的完整性。常見 Hash 演算法有 MD5(已經不安全了)、SHA1、SHA256
結合上述對稱加密和非對稱加密的特點,HTTPS採用混合加密機制
具體過程為:
- 伺服器把 公鑰發給客戶端 去加密 稍後共享密鑰加密 中要使用的密鑰
- 客戶端把 共享密鑰 用伺服器剛發來的公鑰加密,並發給伺服器,伺服器拿到後用私鑰解開,就得到了共享密鑰
- 然後就可以快樂的用共享密鑰來進行通訊
可是問題又來了,
我如何證明我收到的公鑰就是貨真價實伺服器發來的公鑰,而不是壞人發來的釣魚公鑰呢?
數字證書認證機構(CA)
數字證書認證機構處於客戶端與伺服器雙方都可信賴的第三方機構的立場上.
數字證書認證的業務流程:
首先,伺服器 的運營人員向數字證書認證機構提出公開密鑰的申請。
數字證書認證 機構在判明提出申請者的身份之後,會對已申請的公開密鑰做數字簽名,然後分配這個已簽名的公開密鑰,並將該公開密鑰放入公鑰證書後綁定在一起。
伺服器會將這份由數字證書認證機構頒發的公鑰證書發送給客戶端,以進行公開密鑰加密方式通訊。
公鑰證書也可叫做數字證書或直接稱為證書。
接到證書的客戶端可使用數字證書認證機構的公開密鑰,對那張證書 上的數字簽名進行驗證,一旦驗證通過,客戶端便可明確兩件事: 一,認證伺服器的公開密鑰的是真實有效的數字證書認證機構。二, 伺服器的公開密鑰是值得信賴的。
此處認證機關的公開密鑰必須安全地轉交給客戶端。
使用通訊方式時,如何安全轉交是一件很困難的事,因此,多數瀏覽器開發商發布版本時,會事先在內部植入常用認證機關的公開密鑰。
CA認證要花錢么?
CA證書的價格主要受到兩個方面的因素影響,即:品牌和類型。
品牌方面,高端的像Symantec、GlobalSign等,價格基本都在千元到萬元不等,平價的像GeoTrust、Comodo、RapidSSL等,幾百元到幾千元不等。
類型方面,基礎型的DV證書就比較便宜,最低百元左右就能申請。企業型的OV證書和EV證書價格就貴一些,幾百幾千甚至上萬元都有。
總的來說,價格從百元到千元甚至萬元的都有。當然,不同類型的CA證書適用於不同類型的網站。
參考:
//segmentfault.com/a/1190000013028798
//www.ruanyifeng.com/blog/2016/08/http.html
//baijiahao.baidu.com/s?id=1686728003170581869&wfr=spider&for=pc
//baijiahao.baidu.com/s?id=1677802258258817086&wfr=spider&for=pc
《圖解HTTP》
《電腦網路 自頂向下方法》