一,情景

因為golang.org/x/net/websocket未被go團隊納入標準庫,go團隊也未推薦使用,且次庫還有一些問題,並且不再維護。

所以,推薦使用:github.com/gorilla/websocket

安裝命令:

go get github.com/gorilla/websocket@latest

二, 服務端

package main

import (
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"net/url"
)

var UP websocket.Upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin:     func(r *http.Request) bool { return true }, // 測試用,關閉跨域校驗
}

func handler(w http.ResponseWriter, r *http.Request) {
	// ---- 解析查詢參數 ----
	vals, err := url.ParseQuery(r.URL.RawQuery) // 或者 r.URL.Query()
	if err != nil {
		http.Error(w, "invalid query", http.StatusBadRequest)
		return
	}
	cert := vals.Get("cert") // 拿到證書及其他參數

	// ---- 業務:簡單校驗 ----
	if cert == "" {
		http.Error(w, "missing param cert", http.StatusBadRequest)
		return
	}
	log.Printf("握手來自 %s, cert=%s", r.RemoteAddr, cert)
	//升級處理
	conn, err := UP.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	for {
		messageType, p, e := conn.ReadMessage()
		if e != nil {
			log.Println(e)
			break
		}
		fmt.Println(messageType, string(p))
		conn.WriteMessage(messageType, []byte(cert+" : "+string(p)))
	}
	log.Println("服務關閉")
}

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":9999", nil)
}

三, 客户端

package main

import (
	"bufio"
	"fmt"
	"github.com/gorilla/websocket"
	"os"
)

func main() {
	dl := websocket.Dialer{}
	conn, _, err := dl.Dial("ws://127.0.0.1:9999/?cert=kayer", nil)
	if err != nil {
		return
	}
	defer conn.Close()
	conn.WriteMessage(websocket.BinaryMessage, []byte("hello world"))
	go send(conn)
	for {
		m, p, e := conn.ReadMessage()
		if e != nil {
			break
		}
		fmt.Println(m, string(p))
	}
}

func send(conn *websocket.Conn) {
	for {
		reader := bufio.NewReader(os.Stdin)
		l, _, _ := reader.ReadLine()
		conn.WriteMessage(websocket.BinaryMessage, l)
	}
}

四,結果

Go之簡單WebSocket (基礎)_Go