最近因為有需要開發互動式網頁,而且又需要頻繁地和 server 端坐溝通,所以除了 ajax 之外,也開始研究一些新的東西;而其中一個,就是可以更節省頻寬的 WebSocket、這個 HTML 5 的通訊方法了~
關於 WebSocket 的介紹,建議慶直接參考維基百科,或是 WebSocket.org 的介紹;完整的 API 則可以參考 W3C 的網頁。在 Heresy 來看,WebSocket 和傳統的 HTML 資料取得的方法相比,最大的好處,就是由於 WebSocket 是建立一個持續性的連線,不需要重複地不斷建立連線,所以可以有效地降低延遲、並且減少資料的傳輸輛。 像右圖就是 WebSocket.org 所提供的示意圖,可以看到隨著要求存取的次數的增加,傳統的「Polling」的資料存取方法所需的頻寬會上升地非常地快;相較之下,WebSocket 的頻寬則可以省非常地多。 另外,由於 WebSocket 在建立後,可以真正地由 Server 端主動送資料給 client(瀏覽器),所以也可以避免掉一來一往之間的延遲。下方就是 WebSocket.org 的示意圖: 
而目前支援 WebSocket 的瀏覽器列表,可以參考:Can I Use 這個網頁或維基百科。基本上,主要的瀏覽器,只要版本夠新,都是有支援的;比較大的問題,應該會是 IE 要到 10.0 才有支援,而 Android 內建的瀏覽器則完全沒有支援。 WebSocket 的 Client 端,一般就是使用 JavaScript 來做撰寫,然後在瀏覽器內執行;他的基本使用也相當簡單,在 WebSocket.org 的網站裡,就有提供一個「Echo Test」的網頁,算是可以做最基本的說明了~他的範例程式碼如下(Heresy 自己有略做修改): <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>WebSocket Test</title>   <script language="javascript" type="text/javascript"> var wsUri = "ws://echo.websocket.org/"; var output;   function init() { output = document.getElementById("output"); testWebSocket(); }   function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function (evt) { onOpen(evt) };   websocket.onclose = function (evt) { onClose(evt) };   websocket.onmessage = function (evt) { onMessage(evt) };   websocket.onerror = function (evt) { onError(evt) }; }   function onOpen(evt) { writeToScreen("CONNECTED"); doSend("WebSocket rocks"); }   function onClose(evt) { writeToScreen("DISCONNECTED"); }   function onMessage(evt) { writeToScreen('<span style="color:blue;">RESPONSE:' evt.data '</span>'); websocket.close(); }   function onError(evt) { writeToScreen('<span style="color:red;">ERROR:</span>' evt.data); }   function doSend(message) { writeToScreen("SENT: " message); websocket.send(message); }   function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); }   window.addEventListener("load", init, false);   </script> </head>   <body> <h2>WebSocket Test</h2> <div id="output"></div> </body> </html>  首先,在這個網頁裡面,HTML 的部分相當簡單,就是一個 <H2> 的標題,和一個 id 為「output」的 <div>,用來做輸出之用。而在網頁載入完成後,他會去執行 JavaScript 的 init() 這個函式,開始進行 WebSocket 的測試。 實際上 WebSocket 測試的程式,是寫在 testWebSocket() 這個函式裡,它的使用方法相當單純,首先就是要建立一個 WebSocket 的物件,也就是: websocket = new WebSocket(wsUri); 在這邊,傳入的字串 wsUri 的內容是「ws://echo.websocket.org/」,目的是告訴瀏覽器,這個 WebSoscket 是要連到哪裡;在這邊,就是連到 WebSocket.org 提供的測試 Server。而這個 URI 前面的「ws://」,則是代表要使用 WebSocket 這種通訊協定,如果要使用加密的連線的話,則是要改成「wss://」。 後面的網址的部分,則也可以再加上連接埠、或是其他的路徑,來當作進一步的資料;例如:「ws://localhost:12345/websocket/server.php」也是一種合法的 URI(參考)。 而之後,這個建立出來的 websocket 物件,會有四種事件,分別為: 這邊基本上就是要針對這四種事件,來做設定,讓程式可以在事件發生時,做對應的動作。像在上面的範例程式裡,就是設定當這四種事件被觸發的時候,會去呼叫對應的函式(例如,當 onopen 的事件觸發的時候,就去呼叫 onOpen() 這個函式)。 而這個範例網頁用瀏覽器打開後,基本上應該會看到下面的結果: WebSocket Test CONNECTED SENT: WebSocket rocks RESPONSE: WebSocket rocks/message DISCONNECTED 整個程式執行的流程,大致如下: -
首先,當建立了一個 WebSocket 連線後,接下來通常都會是因為能正確地連線,所以會出發到 onopen 的事件,所以會去執行 onOpen() 這個函式;而這個函式所做的事,就是先輸出一個「CONNECTED」的字串,然後再呼叫 doSend() 這個函式,送出「WebSocket rocks」這個字串。 而實際上,要透過 WebSocket 來送出訊息,也相當簡單,只要呼叫 WebSocket 物件(websocket)的 send() 這個函式就可以了~ -
接下來,Server 端的部分,應該是設計成在收到 client 端送來的訊息後,就原封不動地,把訊息再送回給 client 端,所以接下來,這個網頁就會因為收到 Server 端送來的訊息,而觸發到 onmessage 的事件,進而呼叫 onMessage() 這個函式。 而在這個範例程式裡,在收到 Server 端送來的訊息(evt)後,就會把他的資料(evt.data)作輸出(上面藍色的字),並且呼叫 WebSocket 的 close() 函式,把這個連線給關閉。 -
而由於連線被關閉了,所以接下來則是會觸發到 onclose 的事件、進而執行 onClose() 這個函式;在這個函式裡,基本上就是很簡單地輸出「DISCONNECTED」這個字串。 所以到上面為止,就是這個範例的基本概念了~基本上,他是在連線後、傳遞、接收一個訊息後,馬上就把連線斷掉了;而如果再做修改,讓他可以持續地送訊息的話,就可以做到「echo test」這個範例網頁裡,可以持續傳遞、接收資料的功能了~而實際上,WebSocket 的 client 端程式,大概也就是以這樣的概念來寫了。 另外,onmessage 所收到的資料,實際上是一個 MessageEvent 的物件,它除了可以接收字串型別的資料外,其實也是可以接收 Blob(參考)和 ArrayBuffer(參考)這兩種形式的資料,所以在技術上,其實 WebSocket 是可以用來傳輸相當複雜的東西的~
參考:
|