前言

先前在網頁中想取得即時資料。在那個時候有聽到 websocket 這個東西,但一直沒有時間試試。最近剛好又想起了這件事,於是乎這一篇就誕生啦。

本篇會透過一個簡單的範例 echo 來練習使用 WebSocket。

主要內容

Websocket 是基於 HTTP/HTTPS 協定,後續再使用 Upgrade Header 改為 WebSocket 協定。

來個簡單的範例吧

這個範例會實做 2 個部份,一個是使用 Go 語言實作的網頁後端服務,它會提供 WebSocket 伺服端;另一個部份是使用 HTML + Javascript 實作客戶端的部份。

網頁後端

這個範例我們使用的是 gorilla/websocket 實作的版本,我們可以透過下例的指令來使用它。

1go get github.com/gorilla/websocket

echo 函式中會使用 Upgrader 將目前使用的協定從 http 協定改為 WebSocket ,並開始接收來自客戶端的訊息。當收到訊息後,會直接把收到的訊息直接回傳給客戶端。

main.go

 1package main
 2
 3import (
 4	"log"
 5	"net/http"
 6
 7	"github.com/gorilla/websocket"
 8)
 9
10var upgrader = websocket.Upgrader{
11    CheckOrigin: func(r *http.Request) bool {return true},
12}
13
14// 提供 echo 服務
15func echo(w http.ResponseWriter, r *http.Request){
16        c, err := upgrader.Upgrade(w, r, nil)
17        if err != nil {
18            log.Print("upgrade:", err)
19            return
20        }
21        defer c.Close()
22        for {
23        	// 接收到的訊息
24            messageType, message, err := c.ReadMessage()
25            if err != nil {
26                log.Println("read:", err)
27                break
28            }
29            log.Println("read", string(message))
30            	// 送出原本收到的訊息
31            err = c.WriteMessage(messageType, message)
32            if err != nil {
33                log.Println("write:", err)
34                break
35            }
36            log.Println("send", string(message))
37        }
38}
39
40func main(){
41    http.HandleFunc("/ws", echo)
42    http.ListenAndServe(":8080", nil)
43}

網頁前端

index.html

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4    <meta charset="UTF-8">
 5    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 7    <script>
 8        // 載入完成
 9        window.addEventListener("load", function (event) {
10            msg = document.getElementById("msg");
11            btn = document.getElementById("btn");
12            input = document.getElementById("input");
13            
14            // 加上按鈕按下時的處理函式
15            btn.addEventListener("click", event => {
16                console.log("fire~", input.value)
17                ws.send(input.value)
18            })
19            
20            // 建立 websocket 連線
21            let ws = new WebSocket("ws://localhost:8080/ws");
22            ws.onopen = () => {
23                console.log("ws is open");
24            }
25            
26            ws.onclose = () => {
27                console.log("ws is close");
28            }
29            
30            // 加上收到訊息時的處理函式 - 將收到的訊息顯示在 msg 中。
31            ws.onmessage = event => {
32                msg.innerHTML = event.data
33                console.log("roger~~", event.data)
34            }
35            
36            window.addEventListener("beforeunload", function (event) {
37                ws.close()
38            })
39            
40        });
41	</script>
42    <title>WebSocket 測試 - ECHO</title>
43</head>
44<body>
45    <div>
46        <div>收到的訊息</div>
47        <div id="msg"></div>
48    </div>
49    <input type="text" id="input" /><button id="btn">send</button>
50    </body>
51</html>

結果

當我們輸入 hi 並按下 send 時後端會收到我們所傳送的訊息,並立即回傳給前端。

範例執行結果

範例執行結果

小結

本文撰寫了一個非常簡單的範例,主要的目的在於瞭解 WebSocket 的使用方式。實際在使用時,還會有其他的業務邏輯與異常處理的部份。有興趣的同學就再自行玩玩囉~

參考連結