從前端開發看HTTP協議的應用

 

 

 

1、Chrome Developer Network Tabhtml

Cheome Developer做爲如今前端開發者最經常使用的開發調試工具,其具備前端能夠涉及到的各方面的強大功能,爲咱們的開發和定位問題提供了極大地便利。其中Network Tab是至關經常使用的一個功能板塊。經過它的XHR、JS、CSS、Img等子Tab咱們能夠捕獲到全部基於應用層的HTTP/HTTPS協議的網絡請求,能夠查看到該次請求和響應的全部頭信息和內容。前端

Network Tab webpack

展現了針對每個HTTP請求的全部屬性,包括:web

 

其中Connection ID爲傳輸層TCP協議的鏈接ID。關於這點會在下一個章節提到。express

 

Headers主要展現了這次請求的狀態,還有請求和響應的頭部信息,頭部信息是HTTP交互雙方進行做業的依據:npm

Headers中的大多數Key對於有經驗開發者來講並不陌生,不須要在這裏介紹了。但仍是須要提到兩個key:後端

content-type做爲描述交互內容數據MIME格式的key意義至關重大,咱們在實際開發中發出請求缺接收到不到任何東西,若是請求其餘部分沒問題的話,極可能就是由於先後端的content-type不匹配的緣由致使的。api

referer做爲描述請求發起者所屬域的key,也是很是有用的。跨域

1.經過它咱們能夠對網站進行訪問量統計;瀏覽器

2.能夠對任何資源的訪問作域的限制(防盜鏈),好比說:我引用一個QQ空間的圖片URL放到我本身HTTP服務器serve的網頁的<img />上,當我訪問該頁面的時候並無拿到這個圖片,取而代之的是一個訪問受限制的站位圖片。也就是說QQ空間的服務器在接收到資源請求的時候,是對referer作了檢測的,若是非QQ空間的頁面發起的請求是沒法正常獲取到目標圖片的。referer自己是個錯誤的單詞,正確寫法應該爲referrer,譯爲介紹人,描述了是在哪一個域下進行請求資源或者跳轉到某個URL的操做。後來爲了向下兼容HTTP協議,這個錯誤的單詞一直沒有被修改。

須要注意的是:當咱們直接從瀏覽器地址欄訪問某資源時,此時referer爲空,由於此時並不存在有真正的介紹人,這是一個憑空產生的請求,並非從其餘任何地方鏈過去的。

 

 

Response展現了服務端響應的內容,Preview是根據Headers中的雙方的Content-Type的MIME類型加工後的方便開發者瀏覽的帶格式的數據內容:

Cookie展現了在這次請求中瀏覽器Headers中所帶Cookie,以及HTTP服務器端對瀏覽器端Cookie的設置:

 

Timing 整個請求從準備發出到結束的生命週期時序:

對於有經驗的開發者來,從Headers、Preview與Response、Cookie中能獲取到至關有用的信息。對於Timing Tab,它更接近底層,展現了瀏覽器端發起一個HTTP請求的全過程,按照Chrome官方解釋,Timing中各階段描述以下:

1. Queuing(排隊中)

若是一個請求排隊,則代表:

1)請求被渲染引擎推遲,由於它被認爲比關鍵資源(如腳本/樣式)的優先級低。這常常發生在 images(圖像) 上。
2)這個請求被擱置,在等待一個即將被釋放的不可用的TCP socket。
3)這個請求被擱置,由於瀏覽器限制。在HTTP 1協議中,每一個源上只能有6個TCP鏈接,這個問題將在下一面的章節中提到。
4)正在生成磁盤緩存條目(一般很是快)。

2.Stalled/Blocking (中止/阻塞)
發送請求以前等待的時間。它可能由於進入隊列的任何緣由而被阻塞。這個時間包括代理協商的時間。

3.Proxy Negotiation (代理協商)
與代理服務器鏈接協商花費的時間

4.DNS Lookup (DNS查找)

執行DNS查找所用的時間。 頁面上的每一個新域都須要完整的往返(roundtrip)才能進行DNS查找。當本地DNS緩存沒有的時候,這個時間多是有一段長度的,可是好比你一旦在host中設置了DNS,或者第二次訪問,因爲瀏覽器的DNS緩存還在,這個時間就爲0了。

5.Initial Connection / Connecting (初始鏈接/鏈接)
創建鏈接所需的時間, 包括TCP握手/重試和協商SSL。

6.SSL
完成SSL握手所用的時間,若是是HTTPS的話

7.Request Sent / Sending (請求已發送/正在發送)
發出網絡請求所花費的時間。 一般是幾分之一毫秒。

8.Waiting (TTFB) (等待)
等待初始響應所花費的時間,也稱爲`Time To First Byte`(接收到第一個字節所花費的時間)。這個時間除了等待服務器傳遞響應所花費的時間以外,還捕獲到服務器發送數據的延遲時間。這些狀況可能會致使高TTFB:1.客戶端和服務器之間的網絡條件差;2.服務器端程序響應很慢。

9.Content Download / Downloading (內容下載/下載)
接收響應數據所花費的時間。從接收到第一個字節開始,到下載完最後一個字節結束。

經過對請求發出和響應的每一個階段的理解,咱們就能分析出當前HTTP請求存在的問題,並據此解決問題。

 

 

2、客戶端與服務端經過HTTP協議的交互過程

在HTTP協議RFC2616的描述中,HTTP做爲應用層協議,推薦並默認使用TCP/IP做爲傳輸層協議,且其餘任何可靠的傳輸層協議也均可以被HTTP協議採用和使用。也就是說假如UDP是"可靠"的,HTTP也能夠走在UDP上面。目前市面上流行的瀏覽器的HTTP請求廣泛遵照這個原則並採用TCP/IP做爲傳輸層協議。

下面是捕獲的一個對經過XMLHttpRequest對https://localhost:3000/api/syncsystemstatus發起的HTTPS GET請求:

 

在上個章節中有提到Connection ID是TCP鏈接的ID, 代表了這次資源的請求是經過哪個TCP鏈接完成的。

一般狀況下咱們使用Fiddler、Charles或者Chome Developer工具只能對HTTP/HTTPS請求抓包,這裏咱們使用WireShark對更底層的協議鏈接進行封包抓取,並分析上面所提到的這個鏈接從創建到結束的整個過程。WireShark抓包截圖以下:

 

說明:因爲筆者使用Webpack的dev-server給localhost:3000作了正向代理,並開啓了HTTPS,因爲服務器並未開啓HTTPS,因此dev-server到服務器並非HTTPS而是HTTP1.1,192.168.11.94就是dev-server的IP,能夠將其看做localhost:3000,也就是客戶端瀏覽器。192.168.100.101爲dev-server正向代理到的目的地,也是請求要發送到的HTTP服務器。簡單來說該例子就是從瀏覽器(192.168.11.14)經過XMLHttpRequest對象發起了一個到服務器(192.168.100.101)的HTTP1.1請求。

客戶端和服務器交互過程以下:

No.x號爲WireShark封包列表中最左側的列,記錄每一個封包在該次抓取中的編號,並依次遞增。

No.1:瀏覽器(192.168.11.94)向服務器(192.168.100.101)發出鏈接請求,併發送SYN包,進入SYN_SEND狀態,等待服務器確認。這是TCP三次握手的第一次。

 No.2:服務器(192.168.100.101)響應了瀏覽器(192.168.11.94)的請求,確認瀏覽器的SYN(ACK=J+1),而且本身也發送SYN包也就是SYN+ACK包,要求瀏覽器進行確認,此時了服務器進入SYN_RECV狀態。這是TCP三次握手的第二次。

No.3:瀏覽器(192.168.11.94)響應了服務器(192.168.100.101)的SYN+ACK包,向服務器發送確認包ACK(ACK=K+1),此包發送完畢,瀏覽器和服務器進入ESTABLISHED狀態,這是TCP三次握手的第三次,握手完成,TCP鏈接成功創建。

 

No.4:瀏覽器(192.168.11.94)發出一個HTTP請求到服務器(192.168.100.101)。

No.5:服務器(192.168.100.101)收到瀏覽器(192.168.11.94)發出的請求,並確認,而後開始發送數據。

No.6:服務器(192.168.100.101)發送狀態響應碼200到瀏覽器(192.168.11.94),表示數據傳輸成功而且完畢,content-type代表響應的內容文本須要被解析爲JSON格式, OK結束。此時咱們開發者經過判斷XHR的readyState爲4以及status爲200就能夠獲得服務器完整的返回數據並應用在前端邏輯或頁面展現上了。

對應第一章節中提到的Chrome Developer Network的請求時序圖:

1.發起第一個請求並完成鏈接的創建:No.1No.4 對應時序圖中的第5步至第7步。XHR的readyState爲0-2,初始化請求、發送請求並創建鏈接,

2.基於TCP鏈接的創建,經過HTTP協議進行數據傳輸:No.5對應時序圖中的第8步至第9步,XHR的readyState爲3,正在交互中,開始數據。數據傳輸完畢後,readyState爲4,status爲200。

對於Fetch對象發起的請求也是如此的,只不過Fetch基於Promise封裝,readyState和status能夠理解爲是內部控制的,來決定resolve和reject的狀況。筆者的項目實際上是使用Fetch的,只是這裏用XMLHttpRequest對象也就是Ajax來講明,容易理解一些。

針對No.1No.3的TCP的三次握手示意圖:

SYN:Synchronize Sequence Numbers 同步序列編號。

SYN_SEND:請求鏈接,當你要訪問其它的計算機的服務時首先要發個同步信號給該端口,此時狀態爲SYN_SENT,若是鏈接成功了就變爲ESTABLISHED。

ACK:Acknowledgement 確認字符。在數據通訊中,接收站發給發送站的一種傳輸類控制字符。表示發來的數據已確認接收無誤。在TCP/IP協議中,若是接收方成功的接收到數據,那麼會回覆一個ACK數據。一般ACK信號有本身固定的格式,長度大小,由接收方回覆給發送方。

No.4纔是是HTTP的包,這代表HTTP鏈接是基於TCP鏈接創建的。

其餘標識符好比FIN、PSH、RST等能夠參考這裏

而斷開鏈接時須要4次揮手,多1次是由於在主動要求斷開鏈接的那一方不知道被動斷開鏈接的那一方是否還有數據沒有傳輸完畢,被動斷開鏈接的那一方須要把回覆已接收斷開消息和數據已經發送完畢分到2步內進行,不管真實狀況下,在接收到主動方要斷開鏈接的消息時,還有沒有數據須要發送,這2步都必須分開。主動方會一直等待被動方發送FIN碼。其實也能夠用3步完成,可是數據完整性就得不到保證了。有興趣的同窗能夠自行了解下,這裏不作詳細解釋了。

 

3、HTTP因前序請求阻塞而致使後續請求無法發起的問題

筆者目前開發的這個項目早期底層和服務端沒有作緩存優化的時候,從底層Go的接口返回數據給Node.js層,Node.js層再返回給前端界面。在底層接口沒優化的時候,一些操做是現場調用腳本,若是腳本執行耗時長,或者由於網絡抖動緣由致使底層分佈式集羣各節點之間通訊及慢,接口響應速度從幾十毫秒、幾百毫秒到幾秒甚至更長時間不等。前端是基於React.j的SPA應用,每一個界面爲了數據的準確性,在進入界面後會當即請求數據,而且後臺還根據了當前路由維持了一個每15s更新數據的CronJob,定時刷新這個界面的數據。若是暴力的切換路由改變界面能夠在短期內建立大量的HTTP請求。在HTTP1.1下的性能表現極爲糟糕,阻塞狀況嚴重。在Chrome等瀏覽器中,針對同一個域下的HTTP1.1請求同時建立6條TCP鏈接,每條鏈接結束之後才能釋放出來給對另一個資源的請求來使用。雖然和HTTP1.0相比,在性能上已有較大提高,可是並無本質的改變。以本項目爲例,若是當瞬間發起滿10個請求後,只有前6個請求可以分配6個不一樣的HTTP鏈接進行處理,後續4個請求只有等待這6個請求有任何一個釋放HTTP鏈接資源之後,才能繼續。也就是說前6個請求中若是最少耗時都在1s,那麼後4個請求的最少Pending時間都在1s。並且接口的請求都是同一個域,走同一個API網關,沒法經過像相似於請求CDN資源同樣,來把資源請求分散到不一樣的域下。在筆者暴力的操做下,這簡直是噩夢:

 

以getsnapshot這個接口爲例,在不阻塞的狀況下,其大體須要84ms來完成請求:

然而在發生阻塞後:

 

在串行響應的加持下,額...好恐怖。 

 

開啓了webpack-dev-server的HTTPS(經過spdy模塊啓服務)後,瀏覽器默認啓用HTTP/2(HTTP2.0)協議:

 

依舊是暴力操做,瀏覽器在短期內發起大量的請求。能夠看到在ID爲2693483的這個TCP鏈接上,併發處理了的全部的HTTP資源請求,並且它們的開始時間點並非依賴上一個請求的,並且能夠並行響應,即後面的請求響應不會等待前面請求響應完成。

而對於HTPP1.X的keep-alive帶來的優化:在必定時間內,一個域下只要第一次創建HTTP鏈接成功,也就是3次握手成功,那麼後面的HTTP再也不新創建TCP鏈接管道,均使用該次鏈接創建成功之後的管道。避免了沒必要要的鏈接創建的握手過程以及斷開鏈接的揮手過程的耗時。實現了HTTP的持久鏈接和管道流水線(pipelining)。再加上瀏覽器對於HTTP1.1協議處理,都會針對同一個域開闢6個TCP鏈接,必定程度上緩解了瀏覽器端的資源加載壓力。

HTTP1.X雖然解決了HTTP0.X的一些問題,但它在效率上還存在有一些問題:

1. 串行的響應:即使瀏覽器可以同時在一個鏈接的HTTP流水線管道里發起多個請求,服務器也可以在這個管道里響應多個請求,可是請求在服務器端依舊是按照順序給出響應的,也就是說瀏覽器端接收數據的時候,必須是按照發起時的順序來接收。並且瀏覽器對管道流水線的的支持並非太好,要麼不支持,要麼默認關閉的,須要手動設置開啓。對於請求性能和帶寬的利用率提升並未帶來實質性變化。對於這一點瀏覽器提供的單域名6個TCP/HTTP鏈接的優化還能夠必定程度上緩解壓力,可是短期內針對同一域名的請求發起了太多,響應也較慢,阻塞仍是註定會發生的。

2. 請求-響應的數量太多的限制:大多數瀏覽器HTTP1.x對同一個域一個時間段內的請求-響應數量是有限制的,通常爲6個,這致使瀏覽器對網絡帶寬和服務器資源的利用沒法最大化。

既然服務器不能並行響應,那麼僅僅在瀏覽器上可以並行發起請求還有什麼意義呢?也就是說HTTP1.X即使有了keep-alive的加持,它不能算做是全雙工的協議,只能算半雙工的協議。

3.對客戶端和服務端性能消耗大:瀏覽器在HTTP1.X上提供的單域名6個TCP/HTTP鏈接優化,爲了維持這6條鏈接,會致使在請求兩方的機器上都會有額外的性能開銷。

請看如下經過HTTP1.1協議發情請求的截圖:

瞬間並行發起5個請求,瀏覽器在HTTP1.1協議下作了最大優化:即很對同一的請求同時開啓多個(6個)TCP鏈接,並在它們上面建立了對應數量的可複用而且是持久化的HTTP鏈接來處理併發的多個HTTP請求,避免因串行響應而形成的隊頭阻塞。

當咱們間隔必定時間去發起請求,每次都複用的是同一個TCP鏈接:

這已是在HTTP1.1協議下,不修改業務邏輯的條件下能達到的最大優化,還想要性能提升,恐怕就必須使用到一些合併資源請求、CDN資源分發等等方法了。

而HTTP2.0協議改變了上述問題1的串行方式,容許多個請求並行和併發。容許在一個HTTP鏈接內發起多個的請求-響應,而且是多流並行的,卻又不依賴創建多個TCP鏈接。數據經過TCP層進行傳輸的時候,引入了二進制數據幀、流的概念,拋棄了HTTP1.X的基於文本格式的數據傳輸方式,由於這種方式必須按照順序進行請求-響應。轉而使用二進制幀來對數據進行歸類,在幀的頭部注入流的標識符,這樣瀏覽器收到數據以後,經過標識符再將不一樣流的數據合併在一塊兒,能夠並行錯亂或者分級優先地發送(好比遇到圖片和JS都一塊兒請求的時候,能夠給JS資源請求一個較高的有限值,使它被優先處理)。在服務端經過流的標識符進行從新歸類和組裝。極大地提升了發送效率,實現了並行且非阻塞的多路複用。說直白一點:不管客戶端仍是服務器端,均可以一邊並行發送數據一邊並行接收數據。這也就是解決了上面提到的問題1.

對於數據幀內部來講,HTTP1.X的請求-響應首部被放在了HEADERS幀裏面,內容被放到了DATA幀裏面。

對於問題2解決:HTTP2.0對同一域名下全部請求都是基於流的,就是說在同一域名下,無論在客戶端上存在有多少資源的訪問,從理論上講也能夠只創建一個HTTP鏈接的(實際上就是這樣的),經過流來區分不一樣的請求的數據,因此這一個鏈接就能完成整個頁面的資源加載和後期的數據請求,而不用擔憂併發請求-響應的時候會不會出現數據錯亂,筆者認爲這是相對於HTTP1.X的本質改變。服務器的開銷得以減小,處理能力獲得大幅提高。

既然只有一個鏈接的,那麼對資源的開銷問題也會獲得大大的緩解,也就解決了問題3

但HTTP2.0並非使傳輸層TCP變成了並行的鏈接,TCP傳輸層自己的因串行傳輸而帶來的阻塞是沒解決的,僅僅是在應用層HTTP協議上進行了優化,但也正是這些重要的優化使HTTP2.0成爲了全雙工的協議,單鏈接多資源的方式克服了TCP慢啓動帶來的負面影響,更加有效地利用了TCP鏈接,使鏈接性能獲得了極大的提高。也充分地利用了TCP協議的帶寬來下降HTTP延遲,而且減小了鏈接的內存佔用,單個鏈接的吞吐量增大,網略阻塞和丟包的恢復速度增快等。PS. 想要深刻的理解HTTP2.0協議的讀者,能夠自行搜索一些權威資料,這裏再也不作深刻介紹了。

對經過傳統方式進行資源請求優化的影響:一旦HTTP2.0啓用後,咱們可能會根據它的特色去改變一些咱們以前對於靜態資源的處理,能夠減小以前的前端方面在資源請求上的優化工做,特別是資源合併的以減小請求的手段,好比:壓縮到一個js文件以減小HTTP請求、精靈圖片、CSS合併等,這些徹底均可以放開了,這樣作不會再有太大的實際意義。

 

4、SPDY的出現

上個段落咱們提到了HTTP2.0協議針對HTTP1.X版本的優化,可是HTTP2.0在2015年年中才定稿,在這以前要實現HTTP2.0的一些特性一般使用由Google進行推廣的SPDY協議,該協議經歷了四個草案,大量的基於HTTP1.X和SSL/TLS上的優化被IETF採用,做爲HTTP2.0的重要功能點,能夠說SPDY協議是HTTP2.0出現的關鍵前奏。但其終歸是基於HTTP1.X的擴展,除了有相似HTTP2.0的性能提高外,也會有一些HTTP1.X不可克服的問題:好比因隊頭阻塞而使傳輸速度受限制。對於資源請求量小的網站性能提高並不明顯。在安全性方面,SPDY創建在TLS之上,URL scheme也是https,這點和HTTP2.0相同。隨着HTTP2.0的定稿不少瀏覽器也都開始拋棄了SPDY,改成支持HTTP2.0,包括Chrome。筆者曾經遇到一個有意思的問題,就是本文中前個段落提到的在webpack-dev-server開啓了HTTPS,增長了請求併發的性能。但在最新版本的FireFox下訪問,webpack-dev-server的進程會報錯,致使npm start進程死掉。看報錯日誌是由底層stream包報上來的一直到spy包,也就是瀏覽器端和Server端的傳輸協議不太匹配,致使對在Server端對流的操做失敗了。看了webpack-dev-server的源碼他是用express起的server服務,若是配置項HTTPS被設置爲Ture,就生成一些fake的證書之類的,用spdy起服務,不然直接用普通的http模塊起服務。這個腳手架是好久之前的了,它使用的spdy模塊的協議草案版本可能和當前最新的FireFox已經不能適配了。但在Chrome中是OK的,多是自家支持地比較好。找到一個13年老版本的FirFox,進入參數配置界面,關於SPDY部分有如下參數,可供參考:

 

對於HTTP2.0、SPDY、HTTPS在實際實施上,有些方面須要注意:

1. HTTP2.0是能夠不基於HTTPS的,也就是能夠明文傳輸,可是在目前幾大廠商的瀏覽器的實現裏面,都是基於TLS來支持HTTP2.0,因此要實施HTTP2.0,必須先部署HTTPS,但這一點不必定一直是正確的,隨服務端的不一樣部署策略和瀏覽器版本更新,都有可能不一樣。

PS:這裏體現出了協議(標準)和具體應用的實現上的差別。就拿HTTP協議自己來講,協議是無狀態的,但應用在使用協議的時候,能夠在不改變協議的前提下,利用協議預留的加強方式加強協議的功能,好比在客戶端請求頭引入cookie,在服務端響應頭引入session,搭配使用,多個HTTP請求的請求之間就有狀態了,突破了協議自己。因此協議與真實應用上的效果,是有差別的。

2. HTTPS不依賴HTTP2.0,能夠經過HTTP1.1創建鏈接,可是後續或切換協議爲HTTP2.0。

3. SPDY依賴HTTPS,因此若是使用SPDY模塊啓用服務,須要HTTPS相關的準備。webpack-dev-sever要啓動HTTP2.0支持,也只能經過設置env文件HTTPS=true來經過spdy模塊來啓動Express服務,不然直接經過http模塊啓動。

4. 對於不兼容HTTP2.0的瀏覽器,像Nginx這類服務器,會自動降級爲HTTP1.1,以適配瀏覽器端。

這裏再也不作SPDY的詳細介紹,有興趣的同窗能夠搜搜相關資料。

 

5、承前啓後的QUIC

若是你仔細閱讀了上述的內容,你會發現HTTP協議最大的瓶頸實際上是在傳輸層TCP/IP協議自己上面,不管TCP/IP上層的應用層協議怎麼優化,也沒法改變TCP/IP自己過期的設計。因此Google技術推广部在經過SPDY扶正HTTP2之後,又在推基於傳輸層UDP協議的QUIC協議,有可能這就是將來的HTTP3.0協議,對迎接5G時代的來臨極具意義。具體請看筆者轉載的這篇文章

 

6、WebSocket

在實際項目中webscoket協議的出現頻率也是很高的,這裏順帶說一句。websocket鏈接的創建也是先進行TCP握手創建TCP鏈接,再發起HTTP1.x請求進行握手,最後升級(切換)HTTP協議成websocket協議,進而創建websocket鏈接:

 

並且發起websocket鏈接的客戶端的html靜態文件不須要放在HTTP的服務器下面,能夠直接和websocket服務器創建鏈接。也就是說能夠直接經過file://協議在瀏覽器打開一個html文件,在該html內部的<script>腳本里面能夠直接請求server端創建websocket鏈接。

可是按照IETF的websocket協議規範RFC6455,握手請求必須由HTTP協議發出,再進行協議的upgrade,好比:

GET /chat HTTP/1.1

Host: 192.168.12.67:8001

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: dFhlIXNhbXBsZSBub22jZM==

Origin: http://example.com

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

 

注意:13版本的握手協議和舊版本是有區別的。

 

what?這個html文件沒有被HTTP服務器serve,是經過file://協議打開的,竟然還能發出HTTP請求並且沒有跨域?爲何跨域了呢,由於file://協議訪問是沒有域的,location.host爲空。因此後面連着跟了一個/,致使3斜線連在一塊兒了。

從上面的wireshark抓包結果來看,TCP握手成功之後確實是成功發起了HTTP請求的,再升級(切換)HTTP協議成websocket協議的,HTTP的Code爲101(Switching Protocols)。這個多是瀏覽器對websocket API作了特殊處理吧,瀏覽器彷佛代爲發出了到websocket服務器的HTTP跨域請求用於websocket創建前的握手,或者是說websocket服務器在握手階段是支持HTTP的跨域請求?無論是啥緣由,應該都是爲了遵照IETF的RFC6455協議規範。

能夠看出,websocket協議和HTTP處於平級,都是應用層的協議,並非websocket是基於HTTP的,或者HTTP是基於websocket的。只是websocket借鑑了HTTP協議的規範用來創建鏈接,websocket鏈接一旦經過HTTP協議創建成功後,HTTP協議即被拋棄掉了,後續的數據傳輸都是經過websocket協議了,它的握手能夠被HTTP服務器解釋爲一個升級請求。所以它們之間有必定交集。而且在傳輸層上都默認依賴TCP/IP協議。

 

7、HTTP協議與TCP/IP協議之間是什麼關係呢

就如同上面提到的同樣,在WEB通訊中,HTTP協議默認使用TCP/IP協議做爲其在底層依賴的傳輸層協議,固然使用TCP/IP協議並不絕對的,依據協議規範,任何可靠的傳輸層內協議均可以被使用。若是能保證UDP的"可靠",它也可被做爲HTTP協議的傳輸層依賴。若是TCP/IP被比喻成發動機或者底盤之類的底層模塊的話,那麼HTTP協議就是基於這些底層模塊而構建出來的能夠方便使用的具有功能聯合的汽車。經過使用HTTP協議進行網絡通訊的時候,咱們不須要再關注底層的協議棧,只須要按照HTTP協議的請求-響應的約定進行通訊便可。而咱們使用XHR(Ajax)至關於在HTTP協議更上層的API封裝,它提供了create, send 以及狀態變化回調的各類功能函數,而再也不須要本身從頭摸索HTTP協議。就至關於汽車駕校同樣,咱們能夠直接學習到一套標準的開車(=.=)流程輕鬆經過考試,而不須要本身摸索怎麼考過關。

 

好了到此結束吧。

HTTP1.0、HTTP1.一、HTTP2.0之間還有不少的區別,每一個版本之間的變化也很大,包括header壓縮、keep-alive優化、二進制格式、多路複用等。本文只是對在實際項目中遇到的一些應用案例進行介紹,若是對協議自己感興趣,能夠直接閱讀協議規範。

相關文章
相關標籤/搜索