fonchain-fiee/pkg/common/ws/client.go

112 lines
2.8 KiB
Go
Raw Normal View History

2025-06-12 09:07:49 +00:00
// Package ws -----------------------------
// @file : client.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/21 18:18:05
// -------------------------------------------
package ws
import (
"context"
"fmt"
"github.com/gorilla/websocket"
uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
"log"
"strings"
"time"
)
var (
// 注册事件最大等待时间
limitRegisterWaitTime = time.Second * 6
limitReadTime = time.Second * 5
)
// NewClient 创建客户端实例
//
// param userId 用户id
// param uid 用户uuid
// param conn 客户端websocket连接对象
// return *Client
func NewClient(userId int64, uid string, conn *websocket.Conn, room *ChatRoom) *Client {
uidobj, _ := uuid.NewV4()
var v = &Client{
Room: room,
UserId: userId,
Uuid: uid,
ClientId: strings.Replace(uidobj.String(), "-", "", -1),
Conn: conn,
Send: make(chan []byte, 500),
}
return v
}
type Client struct {
Room *ChatRoom `json:"-" `
UserId int64 `json:"userId" ` //用户id
Uuid string `json:"uuid"` //画家uid
ClientId string `json:"clientId"` //为用户不同设备分配不同的客户端ID
Conn *websocket.Conn `json:"-"`
Send chan []byte
SessionId string `json:"sessionId"` //会话ID同一个用户多客户端登录会话ID相同
Waiter bool `json:"waiter"` //是否是客服
}
func (c *Client) Reading(ctx context.Context, handleFunc ...func(sourceData []byte, cli *Client)) {
defer func() {
c.Room.UnRegister <- c
ctx.Done()
return
}()
//c.Conn.SetReadLimit(maxMessageSize)
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
//接收到ping命令后更新读取时间
c.Conn.SetPongHandler(func(string) error {
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
return nil
})
for {
msgType, byteData, err := c.Conn.ReadMessage()
if msgType == -1 {
return
}
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Println("ws连接已关闭", zap.Error(err))
}
break
}
if handleFunc != nil {
handleFunc[0](byteData, c)
} else {
HandleMessage(byteData, c)
}
}
}
func (c *Client) WriteWait() {
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
c.Conn.Close()
}()
for {
select {
case msg, ok := <-c.Send:
fmt.Printf("发送消息:%+v\n", string(msg))
c.Conn.WriteMessage(websocket.TextMessage, msg)
fmt.Println("发送消息结束")
if !ok {
// 聊天室关闭了管道
c.Conn.WriteControl(websocket.CloseMessage, []byte{}, time.Now().Add(writeWait))
return
}
case <-ticker.C:
if err := c.Conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(pongWait)); err != nil {
return
}
}
}
}