// 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 } } } }