今天來介紹通訊協定WebSocket吧,最近都會想主題想一陣子才知道要寫什麼,各種前輩的文章翻來翻去,好就介紹這個吧ˊˇˋ
先看一下wiki介紹
WebSocket是一種網路傳輸協定,可在單個TCP連接上進行全雙工通訊,位於OSI模型的應用層。
WebSocket使得客戶端和伺服器之間的資料交換變得更加簡單,允許伺服器端主動向客戶端推播資料。在WebSocket中,只需要完成一次交握,兩者之間就可以建立永續性的連接,並進行雙向資料傳輸。
在http中,client請求server回應,連線就會中斷了,若是server有更新要傳回,也只能等client發出請求才能回應。若是傳輸頻率很高,就必須讓client不斷發出請求,在效能上的表現並不好,也不能真正取得即時訊息。
而能夠即時通訊的WebSocket協定就在2008年因應而生。
WebSocket是雙向通訊模式,在client送出handshake(握手)建立連線後,即開始雙向模式互動,client與server端都能隨時將資料傳給對方,直到disconnect為止。
我們比較一下WebSocket與http兩種協定有什麼相似之處與相異之處
TCP的一種傳輸協定OSI Layer7協定Http為單向通訊協議;Websocket是雙向通訊。Http為client向server發起連線;WebSocket以Handshake建立連線。Http為短連線,請求結束後會釋放連線;WebSocket建立連線後伺服器會持續監聽請求,不用每次重新連線。Go語言標準套件裡面沒有提供對WebSocket的支援,這邊使用由Gorilla團隊製作的WebSocket套件,gorilla/websocket。
go get github.com/gorilla/websocket
import(
    "github.com/gorilla/websocket"
)
package main
import (
	"log"
	"net/http"
	"fmt"
	"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
func socketHandler(w http.ResponseWriter, r *http.Request) {
    // Upgrade our raw HTTP connection to a websocket based one
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("Error during connection upgradation:", err)
        return
    }
    defer func() {
        log.Println("disconnect !!")
        conn.Close()
    }()
    // The event loop
    for {
        messageType, message, err := conn.ReadMessage()
        if err != nil {
            log.Println("Error during message reading:", err)
            break
        }
        log.Printf("Received: %s", message)
        err = conn.WriteMessage(messageType, message)
        if err != nil {
            log.Println("Error during message writing:", err)
            break
        }
    }
}
func home(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Index Page")
}
func main() {
	http.HandleFunc("/socket", socketHandler)
    log.Println("server start at :8080")
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
寫完後可以將伺服器執行起來
這邊客戶端的功能是每隔一秒會往伺服器傳一次"WebSocket Success!"
package main
import (
	"log"
	"time"
	"github.com/gorilla/websocket"
)
func main() {
	conn, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8080/socket", nil)
	if err != nil {
		log.Fatal("dial:", err)
	}
	defer conn.Close()
	for {
		time.Sleep(time.Second)
		err = conn.WriteMessage(websocket.TextMessage, []byte("WebSocket Success!"))
		if err != nil {
			log.Println(err)
			return
		}
		_, msg, err := conn.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			return
		}
		log.Printf("receive: %s\n", msg)
	}
}
客戶端這邊顯示
output:
2022/10/08 15:54:04 receive: WebSocket Success!
2022/10/08 15:54:05 receive: WebSocket Success!
.
.
.
伺服器端顯示
output:
2022/10/08 15:54:04 Received: WebSocket Success!
2022/10/08 15:54:05 Received: WebSocket Success!
.
.
.
一份WebSocket測試完成了,這邊是最基礎的使用法
慢聊Go之GoLang中使用Gorilla Websocket|Go主题月
https://juejin.cn/post/6946952376825675812
Golang 如何建構一個 websocket server
https://ithelp.ithome.com.tw/articles/10208531
WebSocket
https://ithelp.ithome.com.tw/articles/10249282
WebSocket協議入門介紹
https://iter01.com/420761.html