globalWebSocket.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package controllers
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "time"
  6. "github.com/gofiber/websocket/v2"
  7. "github.com/google/uuid"
  8. "go.uber.org/zap"
  9. )
  10. type WsHandler func(messageType int, p []byte) bool
  11. type Client struct {
  12. ID string
  13. Conn *websocket.Conn
  14. }
  15. type MessageBody struct {
  16. Type string
  17. Data string
  18. }
  19. var clients = make(map[string]*Client)
  20. var handlers = make([]WsHandler, 0)
  21. func GlobalWebSocket(c *websocket.Conn) {
  22. sid := c.Cookies("sid")
  23. if sid == "" {
  24. sid = uuid.New().String()
  25. }
  26. client := &Client{ID: sid, Conn: c}
  27. clients[sid] = client
  28. defer func() {
  29. delete(clients, sid)
  30. c.Close()
  31. }()
  32. fmt.Println("Client connected:", sid)
  33. // 60 秒未收到任何 Pong/消息就判定断线
  34. c.SetReadDeadline(time.Now().Add(60 * time.Second))
  35. c.SetPongHandler(func(appData string) error {
  36. fmt.Println("📡 收到 pong 响应")
  37. c.SetReadDeadline(time.Now().Add(60 * time.Second))
  38. return nil
  39. })
  40. // 启动心跳 goroutine
  41. go func() {
  42. ticker := time.NewTicker(30 * time.Second)
  43. defer ticker.Stop()
  44. for range ticker.C {
  45. if err := c.WriteMessage(websocket.PingMessage, []byte("ping")); err != nil {
  46. fmt.Println("❌ 发送 ping 失败,关闭连接:", err)
  47. c.Close()
  48. return
  49. }
  50. fmt.Println("🟢 发送 ping")
  51. }
  52. }()
  53. for {
  54. // 读取消息
  55. msgType, msg, err := c.ReadMessage()
  56. if err != nil {
  57. zap.L().Error("GlobalWebSocket read err", zap.String("err", err.Error()))
  58. break
  59. }
  60. fmt.Printf("[%s] recv: %s\n", sid, string(msg))
  61. // 处理消息
  62. for _, handler := range handlers {
  63. ok := handler(msgType, msg)
  64. if ok {
  65. break
  66. }
  67. }
  68. }
  69. }
  70. func sendGlobalWebSocketMessage(body MessageBody) {
  71. for _, client := range clients {
  72. if client == nil {
  73. continue
  74. }
  75. payload, err := json.Marshal(body)
  76. if err != nil {
  77. zap.L().Error("json序列化失败", zap.String("err", err.Error()))
  78. continue
  79. }
  80. client.Conn.WriteMessage(websocket.TextMessage, []byte(payload))
  81. }
  82. }
  83. func RegisterGlobalWebSocketHandle(f WsHandler) {
  84. handlers = append(handlers, f)
  85. }
  86. // 以下实现发送各种消息的接口