跳到主要内容

封装客户端对象和Ping客户端

当后端程序运行的时候,第一个客户端发送一个消息之后,刷新页面,然后再发送一个消息,此时的消息是第二个客户端发送的,但是后端没把第一个客户端给移除,因为此时它已经失效了。所以我们需要时不时的和客户端进行交流判断它是否有效,无效则从map里移除

封装建议客户端对象

package core

import (
"github.com/gorilla/websocket"
"time"
)

type WsClient struct {
conn *websocket.Conn
}

func NewWsClient(conn *websocket.Conn) *WsClient {
return &WsClient{conn: conn}
}

func (ws *WsClient) Ping(wait time.Duration) {
for {
time.Sleep(wait)
err := ws.conn.WriteMessage(websocket.TextMessage, []byte("ping"))
if err != nil {
ClientMap.Remove(ws.conn)
return
}
}
}

存储客户端对象添加移除方法

package core

import (
"github.com/gorilla/websocket"
"log"
"sync"
"time"
)

// 存储客户端对象

// ClientMap 外部公共使用
var ClientMap *ClientMapStruct

func init() {
ClientMap = &ClientMapStruct{}
}

type ClientMapStruct struct {
data sync.Map // key 是客户端IP value 是 WsClient 连接对象
}

func (c *ClientMapStruct) Store(conn *websocket.Conn) {
wsClient := NewWsClient(conn)
c.data.Store(conn.RemoteAddr().String(), wsClient)
go wsClient.Ping(time.Second * 1)
}

// SendAll 向所有客户端发送消息
func (c *ClientMapStruct) SendAll(msg string) {
c.data.Range(func(key, value interface{}) bool {
conn := value.(*WsClient).conn
err := conn.WriteMessage(websocket.TextMessage, []byte(msg))
if err != nil {
c.Remove(conn)
log.Println(err)
}
return true
})
}

func (c *ClientMapStruct) Remove(conn *websocket.Conn) {
c.data.Delete(conn.RemoteAddr().String())
}