計算機網絡篇-第2章 應用層協議

一、應用層概述

1.概念

最上層的,也是我們能直接接觸到的就是應用層(Application Layer),我們電腦或手機使用的應用軟件都是在應用層實現。那麼,當兩個不同設備的應用需要通信的時候,應用就把應用數據傳給下一層,也就是傳輸層。

所以,應用層隻需要專註於為用戶提供應用功能,不用去關心數據是如何傳輸的,就類似於,我們寄快遞的時候,隻需要把包裹交給快遞員,由他負責運輸快遞,我們不需要關心快速是如何被運輸的。

而且應用層是工作在操作系統中的用戶態,傳輸層及以下則工作在內核態。

2.常見應用層協議

  • HTTP協議
  • HTTPS協議
  • WebSocket

二、HTTP協議

1.HTTP協議概念

HTTP 是超文本傳輸協議,也就是HyperText Transfer Protocol。

HTTP的名字「超文本協議傳輸」,它可以拆成三個部分:

  • 超文本
  • 傳輸
  • 協議

1.1 協議

在生活中,我們也能隨處可見「協議」,例如:

  • 剛畢業時會簽一個「三方協議」;
  • 找房子時會簽一個「租房協議」;

生活中的協議,本質上與計算機中的協議是相同的,協議的特點:

  • 「協」字,代表的意思是必須有兩個以上的參與者。例如三方協議裡的參與者有三個:你、公司、學校三個;租房協議裡的參與者有兩個:你和房東。
  • 「議」字,代表的意思是對參與者的一種行為約定和規范。例如三方協議裡規定試用期期限、毀約金等;租房協議裡規定租期期限、每月租金金額、違約如何處理等。

針對 HTTP 協議,我們可以這麼理解。

HTTP 是一個用在計算機世界裡的協議。它使用計算機能夠理解的語言確立瞭一種計算機之間交流通信的規范(兩個以上的參與者),以及相關的各種控制和錯誤處理方式(行為約定和規范)。

1.2 傳輸

所謂的「傳輸」,很好理解,就是把一堆東西從 A 點搬到 B 點,或者從 B 點 搬到 A 點。

別輕視瞭這個簡單的動作,它至少包含兩項重要的信息。

HTTP 協議是一個雙向協議。

我們在上網沖浪時,瀏覽器是請求方 A ,百度網站就是應答方 B。雙方約定用 HTTP 協議來通信,於是瀏覽器把請求數據發送給網站,網站再把一些數據返回給瀏覽器,最後由瀏覽器渲染在屏幕,就可以看到圖片、視頻瞭。

數據雖然是在 A 和 B 之間傳輸,但允許中間有中轉或接力。

就好像第一排的同學想穿遞紙條給最後一排的同學,那麼傳遞的過程中就需要經過好多個同學(中間人),這樣的傳輸方式就從「A < — > B」,變成瞭「A <-> N <-> M <-> B」。

而在 HTTP 裡,需要中間人遵從 HTTP 協議,隻要不打擾基本的數據傳輸,就可以添加任意額外的東西。

針對傳輸,我們可以進一步理解瞭 HTTP。

HTTP 是一個在計算機世界裡專門用來在兩點之間傳輸數據的約定和規范。

1.3 超文本

HTTP 傳輸的內容是「超文本」。

我們先來理解「文本」,在互聯網早期的時候隻是簡單的字符文字,但現在「文本」。的涵義已經可以擴展為圖片、視頻、壓縮包等,在 HTTP 眼裡這些都算做「文本」。

再來理解「超文本」,它就是超越瞭普通文本的文本,它是文字、圖片、視頻等的混合體最關鍵有超鏈接,能從一個超文本跳轉到另外一個超文本。

HTML 就是最常見的超文本瞭,它本身隻是純文字文件,但內部用很多標簽定義瞭圖片、視頻等的鏈接,在經過瀏覽器的解釋,呈現給我們的就是一個文字、有畫面的網頁瞭。

OK,經過瞭對 HTTP 裡這三個名詞的詳細解釋,就可以給出比「超文本傳輸協議」這七個字更準確更有技術含量的答案:

HTTP 是一個在計算機世界裡專門在「兩點」之間「傳輸」文字、圖片、音頻、視頻等「超文本」數據的「約定和規范」。

2.HTTP 請求響應過程

讓我們通過⼀個例⼦來探討⼀下 HTTP 的請求響應過程,我們假設訪問的 URL 地址為

http://www.someSchool.edu/someDepartment/home.index ,當我們輸⼊⽹址並點擊回⻋時,瀏覽器內部會進⾏如下操作:

  • DNS服務器會⾸先進⾏域名的映射,找到訪問 http://www.someSchool.edu 所在的地址,然後HTTP 客戶端進程在80 端⼝發起⼀個到服務器 http://www.someSchool.edu 的 TCP 連接(80 端⼝是 HTTP 的默認端⼝)。在客戶和服務器進程中都會有⼀個 套接字Socket 與其相連。
  • HTTP 客戶端通過它的套接字向服務器發送⼀個 HTTP 請求報⽂。該報⽂中包含瞭路徑someDepartment/home.index 的資源,我們後⾯會詳細討論 HTTP 請求報⽂。
  • HTTP 服務器通過它的套接字接收該報⽂,進⾏請求的解析⼯作,並從其 存儲器(RAM 或磁盤) 中檢索出對象http://www.someSchool.edu/someDepartment/home.index,然後把檢索出來的對象進⾏封裝,封裝到 HTTP響應報⽂中,並通過套接字向客戶進⾏發送。
  • HTTP 服務器隨即通知 TCP 斷開 TCP 連接,實際上是需要等到客戶接受完響應報⽂後才會斷開 TCP 連接。
  • HTTP 客戶端接受完響應報⽂後,TCP 連接會關閉。客戶端會從報⽂中提取響應⽂件,並檢查該 HTML ⽂件,然後循環檢查報⽂中其他內部對象。
  • 檢查完成後,HTTP 客戶端會把對應的資源通過顯示器呈現給⽤戶。

⾄此,鍵⼊⽹址再按下回⻋的全過程就結束瞭。上述過程描述的是⼀種簡單的 請求-響應 全過程,真實的請求-響應情況可能要⽐上⾯描述的過程復雜很多。

3.HTTP 請求特征

HTTP 最凸出的優點是「簡單、靈活和易於擴展、應⽤⼴泛和跨平臺」。

3.1 簡單

HTTP 基本的報⽂格式就是 header + body ,頭部信息也是 key-value 簡單⽂本的形式,易於理解,降低瞭學習和使⽤的⻔檻。

3.2 靈活和易於擴展

HTTP協議⾥的各類請求⽅法、URI/URL、狀態碼、頭字段等每個組成要求都沒有被固定死,都允許開發⼈員⾃定義和擴充。

同時 HTTP 由於是⼯作在應⽤層( OSI 第七層),則它下層可以隨意變化。

HTTPS 也就是在 HTTP 與 TCP 層之間增加瞭 SSL/TLS 安全傳輸層,HTTP/3 甚⾄把 TCP 層換成瞭基於 UDP 的QUIC。

3.3 應用廣泛和跨平臺

互聯⽹發展⾄今,HTTP 的應⽤范圍⾮常的⼴泛,從臺式機的瀏覽器到⼿機上的各種 APP,從看新聞、刷貼吧到購物、理財、吃雞,HTTP 的應⽤⽚地開花,同時天然具有跨平臺的優越性。

4.非持久性連接和持久性連接

4.1 非持久性連接HTTP/1.0

我們上⾯描述的 HTTP 請求響應過程就是⼀種 ⾮持久連接 ,因為每次 TCP 在傳遞完報⽂後,都會關閉 TCP 連接,每個 TCP 連接隻傳輸⼀個請求報⽂和響應報⽂。

非持久性連接有⼀些缺點 。

第⼀,必須為每個請求的對象建⽴和維護⼀個全新的連接。

第⼆,對於每個這樣的連接來說,在客戶端和服務器中都要分配 TCP 的緩沖區和保持 TCP 變量,這給 Web服務器帶來瞭嚴重的負擔。因為⼀臺 Web 服務器可能要同時服務於數百甚⾄上千個客戶請求。

早期 HTTP/1.0 性能上的⼀個很⼤的問題,那就是每發起⼀個請求,都要新建⼀次 TCP 連接(三次握⼿),⽽且是串⾏請求,做瞭⽆謂的 TCP 連接建⽴和斷開,增加瞭通信開銷。

4.2 持久性連接HTTP/1.1

為瞭解決上述 TCP 連接問題,HTTP/1.1 提出瞭⻓連接的通信⽅式,也叫持久連接。這種⽅式的好處在於減少瞭TCP 連接的重復建⽴和斷開所造成的額外開銷,減輕瞭服務器端的負載。

持久連接的特點是,隻要任意⼀端沒有明確提出斷開連接,則保持 TCP 連接狀態。服務器發送Http請求時,會在請求頭中發送Connect=keepAlive表示保持長連接。

5.HTTP 報⽂格式

我們上⾯描述瞭⼀下 HTTP 的請求響應過程,相信你對 HTTP 有瞭更深的認識,下⾯我們就來⼀起認識⼀下 HTTP的報⽂格式是怎樣的。

HTTP 協議主要由三⼤部分組成:

  • 起始⾏(start line) :描述請求或響應的基本信息;
  • 頭部字段(header) :使⽤ key-value 形式更詳細地說明報⽂;
  • 消息正⽂(entity) :實際傳輸的數據,它不⼀定是純⽂本,可以是圖⽚、視頻等⼆進制數據。

其中起始⾏和頭部字段並成為 請求頭 或者 響應頭 ,統稱為 Header ;消息正⽂也叫做實體,稱為body。

HTTP 協議規定每次發送的報⽂必須要有 Header,但是可以沒有 body,也就是說頭信息是必須的,實體信息可以沒有。⽽且在 header 和 body 之間必須要有⼀個空⾏(CRLF)。

5.1 HTTP請求報文格式

這幅圖需要註意⼀下,如果使⽤ GET ⽅法,是沒有實體的,如果你使⽤的是 POST ⽅法,才會有實體體。當⽤戶提交表單時,HTTP 客戶端通常使⽤ POST ⽅法;與此相反,HTML 表單的獲取通常使⽤ GET ⽅法。HEAD⽅法類似於 GET ⽅法,隻不過 HEAD ⽅法不會返回對象。

5.2 HTTP 響應報文格式

5.3 請求與響應的區別

可以看到,請求報⽂和響應報⽂隻有請求頭是不同的,其他信息均⼀致。

  • 請求報⽂請求行:

GET /some/page.html HTTP/1.1

  • 響應報文響應行:

HTTP/1.1 200 OK

三、HTTPS協議

1.概念

由於 HTTP 天生“明文”的特點,整個傳輸過程完全透明,任何人都能 夠在鏈路中截獲、修改或者偽造請求 / 響應報文,數據不具有可信性。 因此就誕生瞭為安全而生的HTTPS協議。 使用HTTPS時,所有的HTTP請求和響應在發送到網絡之前,都要進行加密。

2.SSL/TLS

SSL 即安全套接層(Secure Sockets Layer),由網景公司於 1994 年發明,IETF 在 1999 年把它改名為 TLS(傳輸層安全,Transport Layer Security),正式標準化,到今天 TLS 已經發展出瞭主流的三個版本,分別是 2006 年的 1.1、2008 年的 1.2 ,2018的 1.3,每個新版本都緊跟密碼學的發展和互聯網的現狀,持續強化安全和性能,已經成為瞭信息安全領域中的權威標準。

3.摘要算法

摘要算法能夠把任意長度的數據“壓縮”成固定長度、而且獨一無二的“摘要”字符串,就好像是給這段數據生成瞭一個數字“指紋”。

任意微小的數據差異,都可以生成完全不同的摘要。所以可以通過把明文信息的摘要和明文一起加密進行傳輸,數據傳輸到對方之後再進行解密,重新對數據進行摘要,再比對就能發現數據有沒有被篡改。這樣就保證瞭數據的完整性。

明文信息的摘要+明文 ===>加密===》密文–>解密–》對明文進行摘要計算,和解密後的摘要比較。

4.加密算法

4.1 對稱密鑰加密算法

編、解碼使用相同密鑰的算法,如(AES, RC4,ChaCha20 )。

4.2 非對稱密鑰加密算法

它有兩個密鑰,一個叫“公鑰”,一個叫“私鑰”。

兩個密鑰是不同的,公鑰可以公開給任何人使用,而私鑰必須嚴格保密。

非對稱加密可以解決“密鑰交換”的問題。網站秘密保管私鑰,在網上任意分發公鑰,你想要登錄網站隻要用公鑰加密就行瞭,密文隻能由私鑰持有者才能解密。而黑客因為沒有私鑰,所以就無法破解密文。非對稱密鑰加密系統通常需要大量的數學運算,比較慢。如 (DH、DSA、RSA、ECC )

5.TSL加密流程

TLS 裡使用的混合加密方式,即把對稱加密和非對稱加密結合起來呢,兩者互相取長補短,即能高效地加密解密,又能安全地密鑰交換。大致流程如下:

【先使用非對稱加密,後使用對稱加密】

1.通信開始的時候使用非對稱算法如 RSA,ECDHE先解決密鑰交換的問題。

2.用隨機數產生對稱算法使用的"會話密鑰",再用公鑰加密。會話密鑰很短,所以即便使用非對稱加密算法也可以很快完成加解密。

3.對方拿到密文後用私鑰解密,取出會話密鑰。完成對稱密鑰的安全交換,後續就使用對稱算法發完成數據交換。

6.數字證書

6.1 數字證書組成

首先瞭解一下數字證書,它有點像身份證,是由權威的CA機構頒發的,證書的主要內容有:公鑰(Public Key)、ISSUER(證書的發佈機構)、Subject(證書持有者)、證書有效期、簽名算法、指紋及指紋算法。

可以看到公鑰是一串很長的2048 Bits的字符串,同時也可以看到<使用者>的內容包含瞭csdn.net網址,這個網址是CSDN唯一擁有的,後面驗證鏈接url是否正確的時候用到,還有頒發者、有效期、簽名哈希算法等等。當然還有指紋及指紋算法等其他內容,我們滾動到下面看看另外一個截圖

上面是CSDN網站CA證書,頒發者是GeoTrust,它就是權威的CA機構之一。到這裡特別說明一下,CA機構除瞭給別人頒發證書以外,它也有自己的證書,為瞭區分我們稱它為根證書,根證書也有自己的公鑰和私鑰,我們稱之為根公鑰和根私鑰。然後根公鑰和加密算法是向外公佈的,而根私鑰是機構自己絕對保密的。這個根證書在驗證證書的過程中起著核心的作用。

指紋是什麼?指紋是一個證書的簽名,是通過指紋算法sha1計算出來的一個hash值,是用來驗證證書內容有沒有被篡改的。證書在發佈之前,CA機構會把所頒發證書的內容用自己的根私鑰通過指紋算法計算得到一個hash值,這個hash值隻有對應的根公鑰才能解密,所以在驗證證書的時候,我們通過同樣的指紋算法將證書內容通過計算得到另一個hash值,如果這個hash值跟證書上的簽名解析出來的hash值相同,就代表證書沒有被篡改過。

6.2 數字證書的申請

1. 生成自己的公鑰和私鑰,服務器自己保留私鑰

2. 向CA機構提交公鑰,公司,域名信息等待認證

3. CA機構通過線上,線下多種途徑驗證你提交信息的真實性,合法性

4. 信息審核通過,CA機構則會向你簽發認證的數字證書,包含瞭公鑰,組織信息,CA信息,有效時間,證書序列號,同時生成一個簽名;

6.3 HTTPS的數字證書驗證原理

假設這是一個瀏覽器的HTTPS請求

一:首先瀏覽器通過URL網址去請求某個後臺服務器,後臺接收到請求後,就會給瀏覽器發送一個自己的CA數字證書。

二:瀏覽器接收到數字證書以後,就要開始進行驗證工作瞭。

  • 驗證證書的頒發機構是否為瀏覽器的信任機構:首先從證書的內容中獲取證書的頒發機構,然後從瀏覽器系統中去尋找此頒發機構是否為瀏覽器的信任機構。這裡解析一下,世界上就幾個權威的CA機構,這幾個機構的信息都是預先嵌入到我們的瀏覽器系統中的。如果收到的一個數字證書但其頒發機構沒有在我們瀏覽器系統中的,那麼就會有警告提示無法確認證書的真假。如果是受信任的機構,那麼就到下一步。
  • 驗證證書信息是否被修改:此時我們就可以從瀏覽器中找到CA機構的根公鑰,用這個公鑰去解析證書的簽名得到一個hash值H1信息摘要,上面提到過,這個簽名是證書發佈之前CA機構用自己的根私鑰對明文信息的摘要加密而成的,所以這裡隻能由根證書的根公鑰去解密。然後用證書的指紋算法對證書的明文內容再進行hash計算得到另一個hash值H2信息摘要,如果此時H1和H2是相等的,就代表證書沒有被修改過。在證書沒有被修改過的基礎上,再檢查證書上的使用者的URL(比如http://csdn.net)和我們請求的URL是否相等,如果相等,那麼就可以證明當前瀏覽器連接的網址也是正確的,而不是一些釣魚網之類的。

    • 明文加密:【明文信息–》指紋算法–》信息摘要–》根私鑰–》證書的簽名】
    • 機密獲取摘要:【證書的簽名–》根公鑰解密–》信息摘要H1】
    • 生成摘要:【證書明文–》指紋算法–》信息摘要H2】
  • 驗證證書是否是假證書:這裡我們假設,如果瀏覽器的連接被某個釣魚網截取瞭,釣魚網也可以發一個自己的證書給瀏覽器,然後也可以通過證書沒有被篡改的驗證,但是在證書沒有被篡改的情況下,通過對比證書上的URL和我們請求的URL,就可以發現這個證書的URL不是我們所要連接的網址,所以說釣魚網也騙不瞭我們。

三:到這裡,已經驗證瞭證書是沒有被篡改的並且確認連接的URL也是正確的,然後我們獲取到瞭證書上的公鑰。下一步有一個很重要的任務就是,如何將一個對稱加密算法的秘鑰安全地發給服務器。

首先隨機生成一個字符串S作為我們的秘鑰,然後通過證書公鑰加密成密文,將密文發送給服務器。因為此密文是用公鑰加密的,這是一個非對稱加密,我們知道,這個密文隻有私鑰的持有者才能進行解密,所以說任何第三方截取到密文也是沒用的,因為沒有對應的私鑰所以解析不出來。

一個關鍵步驟,發送密文的時候也會對消息內容進行簽名操作。簽名上面講解過,就是對密文內容進行hash計算得到的一個hash值,將這個簽名加密以後和消息內容一起發送出去。接收方收到消息以後,通過私鑰解析出密文和簽名的hash值,同時也會對接收的消息內容進行同樣的計算得到另一個hash值,通過比對兩個hash值是否相同來判斷密文是否有修改過。【通過非對稱加密,確保信息安全。通過簽名算法,確保密文是否是正確的,沒有被替換】

四:通過瞭上面的步驟以後,此時客戶端和服務端都持有瞭對稱加密算法的秘鑰,然後兄弟兩就可以愉快地安全通信瞭。

總結:數字證書的驗證有兩個重要的步驟,第一是驗證數字證書沒有被篡改以及連接的URL是否正確,第二是通過RSA機制的原理安全地將對稱加密算法的秘鑰發送給對方。這兩步都完成以後,整個HTTPS的數字證書的驗證就算是成功瞭。

好瞭,通過上面 的講解,相信我們已經掌握瞭https的數字證書驗證原理瞭。

http://7.CA組織和證書級別

知名的 CA 全世界就那麼幾傢,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,它們簽發的證書級別為:

  • 域名驗證(domain validated,DV)證書、DV可信級別是最低的,隻是域名級別的可信,背後是誰不知道。
  • 組織驗證(organization validated,OV)證書、OV證書可信級別比DV高,會驗證申請證書時填寫的組織,企業信息是 否是正確的,申請往往需要幾天時間。
  • 擴展驗證(extended validation,EV)證書,EV 是最高的,經過瞭法律和審計的嚴格核查,可以證明網站擁有者的身份。

四、WebSocket協議

1.WebSocket協議是什麼

1.1 WebSocket是應用層協議

WebSocket是基於TCP的應用層協議,用於在C/S架構的應用中實現雙向通信,關於WebSocket協議的詳細規范和定義參見rfc6455。需要特別註意的是:雖然WebSocket協議在建立連接時會使用HTTP協議,但這並意味著WebSocket協議是基於HTTP協議實現的。

1.2 WebSocket與Http的區別

實際上,WebSocket協議與Http協議有著本質的區別:

1.通信方式不同

WebSocket是雙向通信模式,客戶端與服務器之間隻有在握手階段是使用HTTP協議的“請求-響應”模式交互,而一旦連接建立之後的通信則使用雙向模式交互,不論是客戶端還是服務端都可以隨時將數據發送給對方;

而HTTP協議則至始至終都采用“請求-響應”模式進行通信。也正因為如此,HTTP協議的通信效率沒有WebSocket高。

2.協議格式不同

WebSocket與HTTP的協議格式是完全不同的,具體來講:

(1)HTTP協議(參見:rfc2616)比較臃腫,而WebSocket協議比較輕量。

(2)對於HTTP協議來講,一個數據包就是一條完整的消息;而WebSocket客戶端與服務端通信的最小單位是幀(frame),由1個或多個幀組成一條完整的消息(message)。即:發送端將消息切割成多個幀,並發送給服務端;服務端接收消息幀,並將關聯的幀重新組裝成完整的消息。

WebSocket協議格式:

HTTP協議格式:

雖然WebSocket和HTTP是不同應用協議,但rfc6455規定:“WebSocket設計為通過80和443端口工作,以及支持HTTP代理和中介”,從而使其與HTTP協議兼容。為瞭實現兼容性,WebSocket握手時使用HTTP Upgrade頭從HTTP協議更改為WebSocket協議,參考:WebSocket維基百科 。

2.為什麼要使用WebSocket

2.1 早期實時刷新的方式

隨著Web應用的發展,特別是動態網頁的普及,越來越多的場景需要實現數據動態刷新。在早期的時候,實現數據刷新的方式通常有如下3種:

2.1.1 客戶端定時查詢

客戶端定時查詢(如:每隔10秒鐘查詢一次)是最原始也是最簡單的實現數據刷新的方法,服務端不用做任何改動,隻需要在客戶端添加一個定時器即可。但是這種方式的缺點也很明顯:大量的定時請求都是無效的,因為服務端的數據並沒有更新,相應地也導致瞭大量的帶寬浪費。

2.1.2 長輪訓機制

長輪訓機制是對客戶端定時查詢的一種改進,即:客戶端依舊保持定時發送請求給服務端,但是服務端並不立即響應,而是等到真正有數據更新的時候才發送給客戶端。

實際上,並不是當沒有數據更新時服務端就永遠都不響應客戶端,而是需要在等待一個超時時間之後結束該次長輪訓請求。相對於客戶端定時查詢方式而言,當數據更新頻率不確定時長輪訓機制能夠很明顯地減少請求數。

但是,在數據更新比較頻繁的場景下,長輪訓方式的優勢就沒那麼明顯瞭。在Web開發中使用得最為普遍的長輪訓實現方案為Comet(Comet (web技術)),Tomcat和Jetty都有對應的實現支持,詳見:WhatIsComet,Why Asynchronous Servlets。

2.1.3 HTTP Streaming

不論是長輪訓機制還是傳統的客戶端定時查詢方式,都需要客戶端不斷地發送請求以獲取數據更新,而HTTP Streaming則試圖改變這種方式,其實現機制為:客戶端發送獲取數據更新請求到服務端時,服務端將保持該請求的響應數據流一直打開,隻要有數據更新就實時地發送給客戶端。

雖然這個設想是非常美好的,但這帶來瞭新的問題:

  • (1)HTTP Streaming的實現機制違背瞭HTTP協議本身的語義,使得客戶端與服務端不再是“請求-響應”的交互方式,而是直接在二者建立起瞭一個單向的“通信管道”。
  • (2)在HTTP Streaming模式下,服務端隻要得到數據更新就發送給客戶端,那麼就需要客戶端與服務端協商如何區分每一個更新數據包的開始和結尾,否則就可能出現解析數據錯誤的情況。
  • (3)另外,處於客戶端與服務端的網絡中介(如:代理)可能會緩存響應數據流,這可能會導致客戶端無法真正獲取到服務端的更新數據,這實際上與HTTP Streaming的本意是相違背的。鑒於上述原因,在實際應用中HTTP Streaming並沒有真正流行起來,反之使用得最多的是長輪訓機制。

2.2 WebSocket協議的特點

顯然,上述幾種實現數據動態刷新的方式都是基於HTTP協議實現的,或多或少地存在這樣那樣的問題和缺陷;而WebSocket是一個全新的應用層協議,專門用於Web應用中需要實現動態刷新的場景。相比起HTTP協議,WebSocket具備如下特點:

  1. 支持雙向通信,實時性更強。
  2. 更好的二進制支持。
  3. 較少的控制開銷:連接創建後,WebSockete客戶端、服務端進行數據交換時,協議控制的數據包頭部較小。
  4. 支持擴展。

3.如何使用WebSocket

3.1 客戶端API

在Web應用的網頁中使用WebSocket,WebSocket對象提供瞭用於創建和管理WebSocket連接,以及可以通過該連接發送和接收數據的API。

3.1.1 構造函數

可以使用WebSocket類的構造函數(WebSocket(url[, protocols]))實例化一個對象,如:

var url = "ws://host:port/endpoint"; var ws = new WebSocket(url);

執行上述語句之後,瀏覽器將與服務端建立一個WebSocket連接,同時返回一個WebSocket實例對象ws。

3.1.2 對象屬性

WebSocket實例對象具備如下屬性:

  • WebSocket.binaryType: 返回websocket連接所傳輸二進制數據的類型。
  • WebSocket.bufferedAmount:隻讀屬性,用於返回已經被send()方法放入隊列中但還沒有被發送到網絡中的數據的字節數。一旦隊列中的所有數據被發送至網絡,則該屬性值將被重置為0。但是,若在發送過程中連接被關閉,則屬性值不會重置為0。如果你不斷地調用send(),則該屬性值會持續增長。
  • WebSocket.extensions:隻讀屬性,返回服務器已選擇的擴展值。目前,鏈接可以協定的擴展值隻有空字符串或者一個擴展列表。
  • WebSocket.protocol:隻讀屬性,用於返回服務器端選中的子協議的名字;這是一個在創建WebSocket對象時,在參數protocols中指定的字符串。
  • WebSocket.readyState:隻讀屬性,返回當前WebSocket對象的鏈接狀態,可能的值為WebSocket中定義的常量:WebSocket.CONNECTING,WebSocket.OPEN,WebSocket.CLOSING,WebSocket.CLOSED。
  • WebSocket.url:隻讀屬性,返回值為當構造函數創建WebSocket實例對象時URL的絕對路徑。
  • WebSocket.onopen:用於指定連接成功後的回調函數,當WebSocket的連接狀態readyState變為“OPEN”時調用;這意味著當前連接已經準備好發送和接受數據,這個事件處理程序通過事件(建立連接時)觸發。
  • WebSocket.onclose:用於指定連接關閉後的回調函數,當WebSocket的連接狀態readyState變為“CLOSED”時被調用,它接收一個名字為“close”的CloseEvent事件對象。
  • WebSocket.onmessage:用於指定當從服務器接受到信息時的回調函數,當從服務器收到一條消息時,該回調函數將被調用,在函數中接受一命名為“message”的MessageEvent事件對象。
  • WebSocket.onerror:用於指定連接失敗後的回調函數,定義一個發生錯誤時執行的回調函數,此事件的事件名為"error"。

3.1.3 對象方法

WebSocket定義瞭2個方法:

(1)WebSocket.send(data):向服務器發送數據,將需要通過WebSocket連接傳輸至服務器的數據排入隊列,並根據所需要傳輸的數據字節的大小來增加屬性bufferedAmount的值 。若數據無法傳輸(例如數據需要緩存而緩沖區已滿)時,套接字會自行關閉。參數data為傳輸至服務器的數據,它必須是以下類型之一:

  • USVString:文本字符串。字符串將以UTF-8格式添加到緩沖區,並且屬性bufferedAmount將加上該字符串以UTF-8格式編碼時的字節數的值。
  • ArrayBuffer:您可以使用一個有類型的數組對象發送底層二進制數據,其二進制數據內存將被緩存於緩沖區,屬性bufferedAmount將加上所需字節數的值。
  • Blob:Blob類型將隊列blob中的原始數據以二進制傳輸,屬性bufferedAmount將加上原始數據的字節數的值。
  • ArrayBufferView:以二進制幀的形式發送任何JavaScript類數組對象,其二進制數據內容將被隊列於緩沖區中,屬性bufferedAmount將加上對應字節數的值。

(2)WebSocket.close([code[, reason]]):關閉當前連接,如果連接已經關閉,則此方法不執行任何操作。

參數:

  • code:可選,為一個數字狀態碼,它解釋瞭連接關閉的原因。如果沒有傳這個參數,默認使用1005。CloseEvent的允許的狀態碼見狀態碼列表。
  • reason:可選,一個人類可讀的字符串,它解釋瞭連接關閉的原因,這個UTF-8編碼的字符串不能超過123個字節。

異常:

  • INVALID_ACCESS_ERR:一個無效的code。
  • SYNTAX_ERR:reason字符串太長(超過123字節)。

更多WebSockete API的詳細內容參見W3C的定義:The WebSocket API。

3.2 在客戶端使用WebSocket

如下為在網頁中使用原生WebSocket的實現方式。

var url = "ws://localhost:8080/websocket/text"; var ws = new WebSocket(url); ws.onopen = function(event) { console.log("websocket connection open."); console.log(event); }; ws.onmessage = function(event) { console.log("websocket message received.") console.log(event.data); }; ws.onclose = function (event) { console.log("websocket connection close."); console.log(event.code); }; ws.onerror = function(event) { console.log("websocket connection error."); console.log(event); };

在Web網頁中使用WebSocket需要瀏覽器支持,不同瀏覽器軟件版本對WebSocket的支持情況詳見瀏覽器兼容性。

另外,WebSocket客戶端除瞭可以在網頁中使用,目前還存在一些獨立的客戶端組件,如:1.Jetty WebSocket Client API

2.websockets-api-java-spring-client

3.Java-WebSocket

3.3 在服務端使用WebSocket

在服務端使用WebSocket需要服務器組件支持,如下以在Tomcat 8.5.41(Tomcat 7之後才支持WebSocket)中使用原生WebSocket為例。由於在服務端使用WebSocket需要使用到WebSocket的API,因此需要添加API依賴管理:

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket-api</artifactId>
<version>8.5.41</version>
</dependency>

赞(0)