Golang WebSocket連接:為何一個標簽頁刷新后其他標簽頁無法收發信息?

Golang WebSocket連接:為何一個標簽頁刷新后其他標簽頁無法收發信息?

golang websocket連接問題:解決標簽頁刷新導致連接中斷

本文分析并解決一個使用Golang Gorilla/WebSocket庫開發的WebSocket應用中出現的棘手問題:chrome瀏覽器打開多個標簽頁連接同一服務器,刷新其中一個標簽頁后,其他標簽頁的WebSocket連接中斷,無法收發信息。

問題描述:

在Go 1.16和Gorilla/WebSocket 1.4.2版本,windows 10環境下,使用Chrome瀏覽器打開兩個標簽頁訪問同一個localhost地址(一個使用localhost,另一個使用IP地址),通過IP地址連接WebSocket服務器。刷新其中一個標簽頁后,該標簽頁的WebSocket連接正常,但另一個標簽頁卻無法收發信息,除非也刷新該標簽頁。

立即學習go語言免費學習筆記(深入)”;

代碼片段(服務器端):

服務器端代碼使用了Gorilla/WebSocket庫和gin框架。關鍵代碼片段如下,展示了錯誤的全局變量用法:

package ws  import (     "encoding/json"     "fmt"     "net/http"     "time"      "github.com/gin-gonic/gin"     "github.com/gorilla/websocket" )  var upgrader = websocket.Upgrader{} // 全局變量,錯誤之處  func ws(c *gin.Context) {     ws, err := upgrader.Upgrade(c.Writer, c.Request, nil) // 錯誤:使用全局變量ws     if err != nil {         return     }     defer ws.Close() // 添加連接關閉時的資源釋放      for {         mt, message, err := ws.ReadMessage()         if err != nil {             break         }         err = ws.WriteMessage(mt, message)         if err != nil {             break         }     } }  // ... (路由配置省略) ...

問題原因及解決方案:

問題根源在于代碼使用了全局變量 ws (websocket.Conn)。這導致所有連接都復用同一個WebSocket連接對象,一個連接的操作會影響其他連接。

解決方案: 移除全局 ws 變量,在 ws 函數中,為每個客戶端連接創建獨立的 websocket.Conn 對象。 在 upgrader.Upgrade 后,直接使用返回的 websocket.Conn 對象進行讀寫操作,并在連接關閉時釋放資源(使用 defer ws.Close())。 正確的代碼如下:

package ws  import (     // ... (導入包省略) ... )  var upgrader = websocket.Upgrader{}  func ws(c *gin.Context) {     ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)     if err != nil {         return     }     defer ws.Close()      for {         mt, message, err := ws.ReadMessage()         if err != nil {             break         }         err = ws.WriteMessage(mt, message)         if err != nil {             break         }     } }  // ... (路由配置省略) ...

通過移除全局變量并為每個連接創建獨立的 websocket.Conn 對象,解決了標簽頁刷新導致其他標簽頁連接中斷的問題。 這確保了每個客戶端連接擁有獨立的資源,互不干擾。

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享