goland 實現(xiàn)websocket server的示例代碼
采用go 實現(xiàn)的websocket,已經(jīng)調試通過在此記錄。
測試工具網(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() {
//客戶端關閉
if err := c.Socket.Close(); err != nil {
fmt.Printf("client [%s] disconnect err: %s", c.Id, err)
}
//關閉后直接注銷客戶端
//WebsocketManager.UnRegisterClient(c)
clientCount--
fmt.Printf("client [%s],客戶端關閉:[%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ù)讀取失敗或通道關閉:[%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() {
//客戶端關閉
if err := c.Socket.Close(); err != nil {
fmt.Printf("client [%s] disconnect err: %s \n", c.Id, err)
return
}
//關閉后直接注銷客戶端
//WebsocketManager.UnRegisterClient(c)
clientCount--
fmt.Printf("client [%s],客戶端關閉:[%s]\n", c.Id, websocket.CloseMessage)
}()
for {
select {
case message, ok := <-c.Message:
if !ok {
//數(shù)據(jù)寫入失敗,關閉通道
fmt.Printf("client [%s],客戶端連接狀態(tài):[%s]\n", c.Id, websocket.CloseMessage)
_ = c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
//消息通道關閉后直接注銷客戶端
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{
//設置允許跨域
CheckOrigin: func(r *http.Request) bool {
return true
},
//設置請求協(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
}
//生成唯一標識client_id
var uuid = uuid.NewV4().String()
client := &Client{
Id: uuid,
Socket: conn,
Message: make(chan []byte, 1024),
}
//注冊
//ws.WebsocketManager.RegisterClient(client)
clientCount++
//起協(xié)程,實時接收和回復數(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": "服務端錯誤",
})
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ù)寫入失敗,關閉通道
fmt.Printf("客戶端連接狀態(tài):[%s]\n", websocket.CloseMessage)
_ = ws.WriteMessage(websocket.CloseMessage, []byte{})
//消息通道關閉后直接注銷客戶端
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")
}
拷貝全部代碼到工程即可測試。
到此這篇關于goland 實現(xiàn)websocket server的示例代碼的文章就介紹到這了,更多相關goland 實現(xiàn)websocket server內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于go-zero單體服務使用泛型簡化注冊Handler路由的問題
這篇文章主要介紹了go-zero單體服務使用泛型簡化注冊Handler路由,涉及到Golang環(huán)境安裝及配置Go Module的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
Golang報“import cycle not allowed”錯誤的2種解決方法
這篇文章主要給大家介紹了關于Golang報"import cycle not allowed"錯誤的2種解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以們下面隨著小編來一起看看吧2018-08-08
使用Golang創(chuàng)建單獨的WebSocket會話
WebSocket是一種在Web開發(fā)中非常常見的通信協(xié)議,它提供了雙向、持久的連接,適用于實時數(shù)據(jù)傳輸和實時通信場景,本文將介紹如何使用 Golang 創(chuàng)建單獨的 WebSocket 會話,包括建立連接、消息傳遞和關閉連接等操作,需要的朋友可以參考下2023-12-12
GO中?分組聲明與array,?slice,?map函數(shù)
這篇文章主要介紹了GO中?分組聲明與array,slice,map函數(shù),Go語言中,同時聲明多個常量、變量,或者導入多個包時,可采用分組的方式進行聲明,下面詳細介紹需要的小伙伴可以參考一下2022-03-03
Windows下在CMD下執(zhí)行Go出現(xiàn)中文亂碼的解決方法
在cmd下運行go程序或者是GOLAND的Terminal下運行go程序會出現(xiàn)中文亂碼的情況。本文就詳細的介紹下解決方法,具有一定的參考價值,感興趣的可以了解一下2021-12-12

