天天看點

細說WebSocket - Node篇

這部分比較簡單,就像路上遇到熟人問好。

握手連接配接中,client 先主動伸手:

用戶端發了一串 Base64 加密的密鑰過去,也就是上面你看到的 Sec-WebSocket-Key。 Server 看到 Client 打招呼之後,悄悄地告訴 Client 他已經知道了,順便也打個招呼。

Server 傳回了 Sec-WebSocket-Accept 這個應答,這個應答内容是通過一定的方式生成的。生成算法是:

key 和 mask 串接之後經過 SHA-1 處理,處理後的資料再經過一次 Base64 加密。分解動作:

上面 Server 端傳回的 HTTP 狀态碼是 101,如果不是 101 ,那就說明握手一開始就失敗了~

下面就來個 demo,跟伺服器握個手:

用戶端代碼:

運作代碼

上面當然是一串不完整的代碼,目的是示範握手過程中,用戶端給服務端打招呼。在控制台我們可以看到:

細說WebSocket - Node篇

看起來很熟悉吧,其實就是發送了一個 HTTP 請求,這個我們在浏覽器的 Network 中也可以看到:

細說WebSocket - Node篇

但是 WebSocket協定 并不是 HTTP 協定,剛開始驗證的時候借用了 HTTP 的頭,連接配接成功之後的通信就不是 HTTP 了,不信你用 fiddler2 抓包試試,肯定是拿不到的,後面的通信部分是基于 TCP 的連接配接。

伺服器要成功的進行通信,必須有應答,往下看:

可以看到

細說WebSocket - Node篇

官方文檔提供了一個結構圖

第一眼瞟到這張圖恐怕是要吐血,如果大學修改計算機網絡這門課應該不會對這東西陌生,資料傳輸協定嘛,是需要定義位元組長度及相關含義的。

資料幀的解析代碼:

細說WebSocket - Node篇

 decodeDataFrame Function

資料幀的編碼:

細說WebSocket - Node篇

 encodeDataFrame Function

有些童鞋可能沒有明白,應該解析哪些資料。這的解析任務主要是服務端處理,用戶端送過去的資料是二進制流形式的,比如: 

Server 收到的資訊是這樣的:

細說WebSocket - Node篇

一個放在Buffer格式的二進制流。而當我們輸出的時候解析這個二進制流:

那輸出的就是一個幀資訊十厘清晰的對象了:

細說WebSocket - Node篇

decodeDataFrame 解析資料,得到的資料格式是:

那麼可以對應上面檢視,此幀的作用就是發送文本,為文本幀。因為連接配接是基于 TCP 的,直接關閉 TCP 連接配接,這個通道就關閉了,不過 WebSocket 設計的還比較人性化,關閉之前還跟你打一聲招呼,在伺服器端,可以判斷frame的Opcode:

用戶端和服務端互動的資料(幀)格式都是一樣的,隻要用戶端發送 <code>ws.close()</code>, 伺服器就會執行上面的操作。相反,如果伺服器給用戶端也發送同樣的關閉幀(close frame):

用戶端就會相應 onclose 函數,這樣的互動還算是有規有矩,不容易出錯。

很多人可能隻知道 <code>ws://text.com:8888</code>,但事實上 websocket 協定位址是可以加 path 和 query 的。

如果使用的是 wss 協定,那麼 URI 将會以安全方式連接配接。 這裡的 wss 大小寫不敏感。

握手請求中包含Sec-WebSocket-Key字段,明眼人一下就能看出來是websocket連接配接,而且這個字段的加密方式在伺服器也是固定的,如果别人想黑你,不會太難。

再就是那個 MaskingKey 掩碼,既然強制加密了(Mask為1表示加密,加密方式就是 MaskingKey 與 PayLoadData 進行異或處理),還有必要讓開發者處理這個東西麼?直接封裝到内部不就行了?

WebSocket協定是一個基于TCP的協定,就是握手連結的時候跟HTTP相關(發了一個HTTP請求),這個請求被Server切換到(Upgrade)websocket協定了。websocket把 80 端口作為預設websocket連接配接端口,而websocket的運作使用的是443端口。

本文轉自Barret Lee部落格園部落格,原文連結:http://www.cnblogs.com/hustskyking/p/websocket-with-node.html,如需轉載請自行聯系原作者

繼續閱讀