goland 實現(xiàn)websocket server的示例代碼
采用go 實現(xiàn)的websocket,已經(jīng)調(diào)試通過在此記錄。
測試工具網(wǎng)址:https://www.idcd.com/tool/socket
話不多說上全部代碼:
package main import ( "fmt" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "net/http" uuid "github.com/satori/go.uuid" ) //Client:單個websocket type Client struct { Id string Socket *websocket.Conn Message chan []byte } var clientCount uint // 客戶端數(shù)量 //從websocket中直接讀取數(shù)據(jù) func (c *Client) Read() { defer func() { //客戶端關(guān)閉 if err := c.Socket.Close(); err != nil { fmt.Printf("client [%s] disconnect err: %s", c.Id, err) } //關(guān)閉后直接注銷客戶端 //WebsocketManager.UnRegisterClient(c) clientCount-- fmt.Printf("client [%s],客戶端關(guān)閉:[%s],Count [%d]\n", c.Id, websocket.CloseMessage, clientCount) }() for { messageType, message, err := c.Socket.ReadMessage() //讀取數(shù)據(jù)失敗 if err != nil || messageType == websocket.CloseMessage { fmt.Printf("client [%s],數(shù)據(jù)讀取失敗或通道關(guān)閉:[%s],客戶端連接狀態(tài):[%s]\n", c.Id, err.Error(), websocket.CloseMessage) break } // TODO 解析發(fā)送過來的參數(shù) //var data ReadData //err = json.Unmarshal(message, &data) //if err != nil { // fmt.Println("數(shù)據(jù)解析失敗") // return //} // TODO 前端請求返回數(shù)據(jù)到指定客戶端 // 簡單測試 c.Message <- message } } //寫入數(shù)據(jù)到websocket中 func (c *Client) Write() { defer func() { //客戶端關(guān)閉 if err := c.Socket.Close(); err != nil { fmt.Printf("client [%s] disconnect err: %s \n", c.Id, err) return } //關(guān)閉后直接注銷客戶端 //WebsocketManager.UnRegisterClient(c) clientCount-- fmt.Printf("client [%s],客戶端關(guān)閉:[%s]\n", c.Id, websocket.CloseMessage) }() for { select { case message, ok := <-c.Message: if !ok { //數(shù)據(jù)寫入失敗,關(guān)閉通道 fmt.Printf("client [%s],客戶端連接狀態(tài):[%s]\n", c.Id, websocket.CloseMessage) _ = c.Socket.WriteMessage(websocket.CloseMessage, []byte{}) //消息通道關(guān)閉后直接注銷客戶端 return } err := c.Socket.WriteMessage(websocket.TextMessage, message) if err != nil { fmt.Printf("client [%s] write message err: %s \n", c.Id, err) return } } } } // 方法二: 通過對象創(chuàng)建 客戶端連接 func WsClient(context *gin.Context) { upGrande := websocket.Upgrader{ //設(shè)置允許跨域 CheckOrigin: func(r *http.Request) bool { return true }, //設(shè)置請求協(xié)議 Subprotocols: []string{context.GetHeader("Sec-WebSocket-Protocol")}, } //創(chuàng)建連接 conn, err := upGrande.Upgrade(context.Writer, context.Request, nil) if err != nil { fmt.Printf("websocket connect error: %s", context.Param("channel")) //format.NewResponseJson(context).Error(51001) return } //生成唯一標(biāo)識client_id var uuid = uuid.NewV4().String() client := &Client{ Id: uuid, Socket: conn, Message: make(chan []byte, 1024), } //注冊 //ws.WebsocketManager.RegisterClient(client) clientCount++ //起協(xié)程,實時接收和回復(fù)數(shù)據(jù) go client.Read() go client.Write() } // 方法一: 直接創(chuàng)建客戶端 func NewConnection(c *gin.Context) { // 定義同源檢查,這里只作簡單試驗不校驗 upGrader := websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) //ws, err := websocket.Upgrade(c.Writer, c.Request, nil, 1024, 1024) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "msg": "服務(wù)端錯誤", }) return } var message = make(chan []byte) go func() { defer ws.Close() for { fmt.Println("start transfer message") msgType, msg, err := ws.ReadMessage() if err != nil || websocket.CloseMessage == msgType { fmt.Println("webSocket read error") return } message <- msg } }() go func() { defer ws.Close() for { mm, ok := <- message if !ok { //數(shù)據(jù)寫入失敗,關(guān)閉通道 fmt.Printf("客戶端連接狀態(tài):[%s]\n", websocket.CloseMessage) _ = ws.WriteMessage(websocket.CloseMessage, []byte{}) //消息通道關(guān)閉后直接注銷客戶端 return } err := ws.WriteMessage(websocket.TextMessage, mm) if err != nil { fmt.Println("webSocket write error") return } } }() //for { // //} 開始通信 //for { // fmt.Println("start transfer message") // msgType, msg, err := ws.ReadMessage() // if err != nil { // fmt.Println("webSocket read error") // return // } // err = ws.WriteMessage(msgType, msg) // if err != nil { // fmt.Println("webSocket write error") // return // } //} } // ws://127.0.0.1:9090/wsTest func main() { r := gin.Default() // 方法一: 直接創(chuàng)建客戶端 r.GET("/wsTest", NewConnection) // 方法二: 通過對象創(chuàng)建 客戶端連接 r.GET("/wsTest1", WsClient) clientCount = 0 r.Run("127.0.0.1:9090") }
拷貝全部代碼到工程即可測試。
到此這篇關(guān)于goland 實現(xiàn)websocket server的示例代碼的文章就介紹到這了,更多相關(guān)goland 實現(xiàn)websocket server內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何在golang中使用shopspring/decimal來處理精度問題
本文主要介紹了如何在golang中使用shopspring/decimal來處理精度問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04GoLang基礎(chǔ)學(xué)習(xí)之go?test測試
相信每位編程開發(fā)者們應(yīng)該都知道,Golang作為一門標(biāo)榜工程化的語言,提供了非常簡便、實用的編寫單元測試的能力,下面這篇文章主要給大家介紹了關(guān)于GoLang基礎(chǔ)學(xué)習(xí)之go?test測試的相關(guān)資料,需要的朋友可以參考下2022-08-08