公司的 WebSocket Server 使用 node.js Primus 建構服務,最近正在調整架構,弄隻 WebSocket Client 交叉比對,這時就想到 Golang 可以練一下 XD 預設先以 PTT 的 WebSocket 為例 wss://ws.ptt.cc/bbs 練習,而 PTT WebSocket 連線時,有檢查 Request Header 的 Origin 欄位的,完整的用法請直接使用 https://term.ptt.cc 。
實作上,直接用 Gorilla WebSocket 即可,用他建制 WebSocket server 跟 client。
此外,對於 WebSocket over SSL (wss) 連線瑣事上,若要處理 SKIP SSL Check 這件事,可以這樣處理:
// https://pkg.go.dev/crypto/tlstype zeroSource struct{}func (zeroSource) Read(b []byte) (n int, err error) {for i := range b {b[i] = 0}return len(b), nil}func main() {// ...var dialer ws.Dialerif *skipSSLCheck {fmt.Println("[IFNO] Skip SSL check")// https://github.com/gorilla/websocket/blob/master/client.go// https://github.com/gorilla/websocket/blob/master/tls_handshake.godialer = ws.Dialer{Subprotocols: []string{},ReadBufferSize: 2048,WriteBufferSize: 2048,TLSClientConfig: &tls.Config{Rand: zeroSource{},InsecureSkipVerify: true,},}} else {dialer = ws.Dialer{Subprotocols: []string{},ReadBufferSize: 2048,WriteBufferSize: 2048,}}fmt.Println("[IFNO] try to connect to: ", connectToURL)// ...}
至於跟 node.js Primus WebSocket server 溝通時,會有 PING/PONG 的 heartbeat 檢驗,目前偷懶等收到 server 詢問時才回,此外,實際上可以靠 messageType (Control Messages) 來判斷:
go func() {defer func() {wg.Done()}()for {_, p, err := conn.ReadMessage()if err == nil {cmd := string(p)fmt.Println("SERVER> ", cmd)if strings.Index(cmd, "\"primus::ping::") >= 0 {text := fmt.Sprintf("\"primus::ping::%d\"", time.Now().UnixMilli())fmt.Println("CLIENT:AUTO> [",text,"]")conn.WriteMessage(ws.TextMessage, []byte(text))}} else {fmt.Println("SERVER:ERROR> ", err)break}}fmt.Println("[IFNO] server error")}()
更多完整的資訊,就直接參考 github.com/changyy/go-ws-client 吧
沒有留言:
張貼留言