天天看點

WebScoket

#WebSocket 是 html5 新增加的一種通信協定,目前流行的浏覽器都支援這個協定,例如 Chrome,Safrie,Firefox,Opera,IE 等等。

WebSocket API

首先看一段簡單的 javascript 代碼,該代碼調用了 WebSockets 的 API。

var ws = new WebSocket(“ws://echo.websocket.org”);
ws.onopen = function(){ws.send(“Test!”); };
ws.onmessage = function(evt){console.log(evt.data);ws.close();};
ws.onclose = function(evt){console.log(“WebSocketClosed!”);};
ws.onerror = function(evt){console.log(“WebSocketError!”);};
           

這份代碼總共隻有 5 行,現在簡單概述一下這 5 行代碼的意義。

第一行代碼是在申請一個 WebSocket 對象,參數是需要連接配接的伺服器端的位址,同 http 協定使用

http://

開頭一樣,WebSocket 協定的 URL 使用

ws://

開頭,另外安全的 WebSocket 協定使用

wss://

開頭。

第二行到第五行為 WebSocket 對象注冊消息的處理函數,WebSocket 對象一共支援四個消息

onopen

,

onmessage

,

onclose

onerror

當 Browser 和 WebSocketServer 連接配接成功後,會觸發

onopen

消息;

如果連接配接失敗,發送、接收資料 失敗或者處理資料出現錯誤,browser 會觸發

onerror

消息;

當 Browser 接收到 WebSocketServer 發送過來的資料時,就會觸發

onmessage

消息,參數 evt 中包含 server 傳輸過來的資料;

當 Browser 接收到 WebSocketServer 端發送的關閉連接配接請求時, 就會觸發

onclose

消息。

我們可以看出 所有的操作都是采用消息的方式觸發的,這樣就不會阻塞 UI,使得 UI 有更快的響應時間,得到更好的使用者體驗。

WebSocket 協定

WebSocket 協定是一種雙向通信協定,它建立在 TCP 之上,同 http 一樣通過 TCP 來傳輸資料,但是它和 http 最大的不同有兩點:

  1. WebSocket 是一種雙向通信協定,在建立連接配接後,WebSocket 伺服器和 Browser/UA 都能主動的向對方發送或接收資料,就像 Socket 一樣,不同的是 WebSocket 是一種建立在 Web 基礎上的一種簡單模拟 Socket 的協定。
  2. WebSocket 需要通過握手連接配接,類似于 TCP 它也需要用戶端和伺服器端進行握手連接配接,連接配接成功後才能互相通信。

下面是一個簡單的建立握手的時序圖:

WebScoket

這裡簡單說明一下 WebSocket 握手的過程。

當 Web 應用程式調用

new WebSocket(url)

接口時,Browser 就開始了與位址為 url 的 WebServer 建立握手連接配接的過程。

  1. Browser 與 WebSocket 伺服器通過 TCP 三次握手建立連接配接,如果這個建立連接配接失敗,那麼後面的過程就不會執行,Web 應用程式将收到錯誤消息通知。
  2. 在 TCP 建立連接配接成功後,Browser/UA 通過 http 協定傳送 WebSocket 支援的版本号,協定的字版本号,原始位址,主機位址等等一些列字段給伺服器端。

例如:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
           
  1. WebSocket 伺服器收到 Browser/UA 發送來的握手請求後,如果資料包資料和格式正确,用戶端和伺服器端的協定版本号比對等等,就接受本次握手連接配接,并給出相應的資料回複,同樣回複的資料包也是采用 http 協定傳輸。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
           
  1. Browser 收到伺服器回複的資料包後,如果資料包内容、格式都沒有問題的話,就表 示本次連接配接成功,觸發

    onopen

    消息,此時 Web 開發者就可以在此時通過

    send

    接口想伺服器發送資料。

否則,握手連接配接失敗,Web 應用程式會收到

onerror

消息,并且能知道連接配接失敗的原因。

websocket 與 TCP,HTTP 的關系

WebSocket 與 http 協定一樣都是基于 TCP 的,是以他們都是可靠的協定,Web 開發者調用的 WebSocket 的

send

函數在 browser 的實作中最終都是通過 TCP 的系統接口進行傳輸的。

WebSocket 和 Http 協定一樣都屬于應用層的協定,那麼他們之間有沒有什麼關系呢?

答案是肯定 的,WebSocket 在建立握手連接配接時,資料是通過 http 協定傳輸的,正如我們上一節所看到的“GET/chat HTTP/1.1”,這裡面用到的隻是 http 協定一些簡單的字段。但是在建立連接配接之後,真正的資料傳輸階段是不需要 http 協定參與的。

WebScoket

websocket server

如果要搭建一個 Web 伺服器,我們會有很多選擇,市場上也有很多成熟的産品供我們應用,比如開源的 Apache,安裝後隻需簡單的配置(或者預設配置)就可 以工作了。

但是如果想搭建一個 WebSocket 伺服器就沒有那麼輕松了,因為 WebSocket 是一種新的通信協定,目前還是草案,沒有成為标準,市場 上也沒有成熟的 WebSocket 伺服器或者 Library 實作 WebSocket 協定,我們就必須自己動手寫代碼去解析群組裝 WebSocket 的資料 包。

要這樣完成一個 WebSocket 伺服器,估計所有的人都想放棄,幸好的是市場上有幾款比較好的開源庫供我們使用,比如 PyWebSocket,WebSocket-Node, LibWebSockets 等等,這些庫檔案已經實作了 WebSocket 資料包的封裝和解析,我們可以調用這些接口,這在很大程度上減少了我們的工作量。如

github

websocket 是可以和 http 共用監聽端口的,也就是它可以公用端口完成 socket 任務

關于 Socket 與 WebScoket

Socket 其實并不是一個協定。

它工作在 OSI 模型會話層(第 5 層),是為了友善大家直接使用更底層協定(一般是 TCP 或 UDP )而存在的一個抽象層。

最早的一套 Socket API 是 Berkeley sockets ,采用 C 語言實作。它是 Socket 的事實标準,POSIX sockets 是基于它建構的,多種程式設計語言都遵循這套 API,在 JAVA、Python 中都能看到這套 API 的影子。

Socket 是應用層與 TCP/IP 協定族通信的中間軟體抽象層,它是一組接口。

在設計模式中,Socket 其實就是一個門面模式,它把複雜的 TCP/IP 協定族隐藏在 Socket 接口後面,對使用者來說,一組簡單的接口就是全部,讓 Socket 去組織資料,以符合指定的協定。

主機 A 的應用程式要能和主機 B 的應用程式通信,必須通過 Socket 建立連接配接,而建立 Socket 連接配接必須需要底層 TCP/IP 協定來建立 TCP 連接配接。建立 TCP 連接配接需要底層 IP 協定來尋址網絡中的主機。我們知道網絡層使用的 IP 協定可以幫助我們根據 IP 位址來找到目标主機,但是一台主機上可能運作着多個應用程式,如何才能與指定的應用程式通信就要通過 TCP 或 UPD 的位址也就是端口号來指定。

這樣就可以通過一個 Socket 執行個體唯一代表一個主機上的一個應用程式的通信鍊路了。

而 WebSocket 則不同,它是一個完整的 應用層協定,包含一套标準的 API 。

是以,從使用上來說,WebSocket 更易用,而 Socket 更靈活。

再簡單來說, Socket 是一個應用程式接口,是抽象的,WebSocket 和 HTTP 是具體實作,

WebScoket