package webstocetmsg import ( "context" "encoding/json" "errors" "fmt" "net" "net/http" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) var upGraderes = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func (a *ApiMethod) Regist(c *gin.Context) { conn, err := upGraderes.Upgrade(c.Writer, c.Request, nil) if err != nil { fmt.Println("websocket error:", err) return } //得到客户的连接ip和端口 fmt.Println("client connect:", conn.RemoteAddr()) go a.Do(conn) } func (a *ApiMethod) Do(conn *websocket.Conn) { for { //获取到前端发送过来的websocket消息 contentType, message, err := conn.ReadMessage() if err != nil { //判断是不是超时 if netErr, ok := err.(net.Error); ok { if netErr.Timeout() { fmt.Printf("ReadMessage timeout remote:%v\n", conn.RemoteAddr()) } } // 其他错误,如果是 1001 和 1000,就不打印日志 if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) { fmt.Println("其他错误") } conn.Close() //这边必须return,因为前端的链接可能某个时间段就断开链接了,要是没有return,会导致产生 repeated read on failed websocket connection报错,而且也可以防止内存泄露 return } fmt.Printf("contentType:%v\n", contentType) fmt.Printf("message:%v\n", string(message)) //写入ws msg := []byte("我是server") err = conn.WriteMessage(1, msg) if err != nil { fmt.Println("发生错误了") fmt.Println(err.Error()) } } } func (c *Client) SendOut(message *Message) error { content, err := json.Marshal(message.Content) if err != nil { return err } c.Send <- content return nil } func (manager *ClientManager) Write(message *Message) error { manager.RLock() client, ok := manager.Clients[message.Recipient] manager.RUnlock() if !ok { return errors.New("client miss [" + message.Recipient + "]") } return client.SendOut(message) } /* * @ 作者: 秦东 @ 时间: 2024-08-16 16:14:22 @ 功能: Start 方法提供监听注册、注销以及续期的 channel,通过监听这些 channel 来管理创建的连接对象。当这些 channel 有数据时,执行对应的操作。 @ 参数 # @ 返回值 # @ 方法原型 # */ func (manager *ClientManager) Start(ctx context.Context) { // for { // select { // case conn := <-manager.Register: // manager.Lock() // manager.Clients[conn.UUID] = conn // manager.Unlock() // _, err := manager.affair.Register(ctx, &RegisterReq{ // UserID: conn.UserID, // UUID: conn.UUID, // IP: manager.IP, // }) // case conn := <-manager.Unregister: // _, err := manager.affair.Unregister(ctx, &UnregisterReq{ // UserID: conn.UserID, // UUID: conn.UUID, // }) // conn.Socket.Close() // close(conn.Send) // delete(manager.Clients, conn.UUID) // case conn := <-manager.Renewal: // //... // // Key renewal to redis // } // } }