Table of Contents
前言
這篇不會涉及太多底層的基礎知識
主要是分享自己在 Golang Websocket on Gin 這邊使用到的程式碼
方便各位進來直接複製🤣
這篇文章會從建立開始
會包含到所使用的套件以及範例的程式碼
到最後的用小程式來驗證
什麼是 Websocket
以下引述自維基百科
WebSocket是一種網絡傳輸協議
可在單個TCP連接上進行全雙工通信,位於OSI模型的應用層。
WebSocket協議在2011年由IETF標準化為RFC 6455,後由RFC 7936補充規範。Web IDL中的WebSocket API由W3C標準化。
WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就可以建立持久性的連接,並進行雙向數據傳輸。
幫各位畫了重點
- 全雙工:無論是 Server 端,或者 Client 端都可以同時傳送跟接收資料
- 一次握手:跟一般 HTTP 通訊需要完成三方交握不同,Websocket 僅需要完成一次握手
綜合以上兩點,Websocket 就是高即時性,低延遲
但同時,更考驗錯誤處理
再統整一些我的筆記
- 連線一旦建立之後,除非任何一端關閉,否則連線會一直存在
- Server 端可以主動傳送資料給 Client,即使 Client 並沒有送請求(就像聊天室)
- 有兩種 URI
ws://
:使用於非加密連線wss://
:使用於加密連線,使用 443 port
使用套件
Gorilla WebSocket
// import "github.com/gorilla/websocket"
go get -u github.com/gorilla/websocket
Gin
// import "github.com/gin-gonic/gin"
go get -u github.com/gin-gonic/gin
從 HTTP Server 開始
// ServeHTTP ServeHTTP
func ServeHTTP() {
go func() {
g := gin.New()
g.Use(gin.Recovery())
err := g.SetTrustedProxies(nil)
if err != nil {
panic(err)
}
public := g.Group("/socket")
public.GET("", SocketHandler)
if err := g.Run(":8080"); err != nil {
panic(err)
}
}()
}
到這邊為止
只是用 Gin 建立了一個 http server
並將 /socket 設定為 websocket 路由
HandlerFunc 在文章後面會有說明
使用 upgrader() 將 HTTP 連線轉化成 Websocket
引用自 pkg.go.dev
Upgrader specifies parameters for upgrading an HTTP connection to a WebSocket connection.
It is safe to call Upgrader’s methods concurrently.
upgrader 參數如下
CheckOrigin:會檢查是否跨域,文章後面的測試工具會提到 true, false 差別
Buffer:單位是 bytes,依需求設定(設為 0,則為不限制大小)
upGrader := websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
Golang Websocket on Gin
將 upgrader 加入 Gin API Handler
func SocketHandler(c *gin.Context) {
upGrader := websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
panic(err)
}
defer func() {
closeSocketErr := ws.Close()
if closeSocketErr != nil {
panic(err)
}
}()
for {
msgType, msg, err := ws.ReadMessage()
if err != nil {
panic(err)
}
fmt.Printf("Message Type: %d, Message: %s\n", msgType, string(msg))
err = ws.WriteJSON(struct {
Reply string `json:"reply"`
}{
Reply: "Echo...",
})
if err != nil {
panic(err)
}
}
}
測試連線建立(PIE SOCKET)
這邊推薦一個不用寫 Code 就能夠驗證的方法
這是一個 Google Chrome 的外掛(連結)
使用方法也很簡單
可以直接輸入 ws://…. 並 CONNECT
或者像我一樣 OPEN FULLSIZE 到新分頁執行
以本篇的範例來說
網址:ws://127.0.0.1:8080/socket
CONNECT 之後會變成 SEND MESSAGE
以下為執行結果