websocket_manager.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package common
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "sync"
  7. "time"
  8. "github.com/gorilla/websocket"
  9. )
  10. var upgrader = websocket.Upgrader{
  11. CheckOrigin: func(r *http.Request) bool {
  12. return true // 允许所有来源
  13. },
  14. }
  15. // WebSocketConnection WebSocket连接信息
  16. type WebSocketConnection struct {
  17. ID string
  18. Conn *websocket.Conn
  19. LastSendTime time.Time
  20. LastDataHash string
  21. IsFirstSend bool
  22. SendChan chan []byte
  23. mu sync.Mutex
  24. }
  25. // WebSocketManager WebSocket管理器
  26. type WebSocketManager struct {
  27. connections map[string]*WebSocketConnection
  28. mutex sync.RWMutex
  29. broadcast chan []byte
  30. register chan *WebSocketConnection
  31. unregister chan *WebSocketConnection
  32. }
  33. // 全局WebSocket管理器实例
  34. var GlobalWSManager = &WebSocketManager{
  35. connections: make(map[string]*WebSocketConnection),
  36. broadcast: make(chan []byte, 100),
  37. register: make(chan *WebSocketConnection, 10),
  38. unregister: make(chan *WebSocketConnection, 10),
  39. }
  40. // Start 启动WebSocket管理器
  41. func (m *WebSocketManager) Start() {
  42. go m.handleMessages()
  43. go m.cleanupStaleConnections()
  44. }
  45. // handleMessages 处理连接消息
  46. func (m *WebSocketManager) handleMessages() {
  47. for {
  48. select {
  49. case conn := <-m.register:
  50. m.mutex.Lock()
  51. m.connections[conn.ID] = conn
  52. m.mutex.Unlock()
  53. log.Printf("WebSocket客户端已连接: %s", conn.ID)
  54. case conn := <-m.unregister:
  55. m.mutex.Lock()
  56. if _, exists := m.connections[conn.ID]; exists {
  57. delete(m.connections, conn.ID)
  58. conn.Conn.Close()
  59. close(conn.SendChan)
  60. }
  61. m.mutex.Unlock()
  62. log.Printf("WebSocket客户端已断开: %s", conn.ID)
  63. case message := <-m.broadcast:
  64. m.mutex.RLock()
  65. for _, conn := range m.connections {
  66. select {
  67. case conn.SendChan <- message:
  68. conn.LastSendTime = time.Now()
  69. default:
  70. log.Printf("发送队列已满,关闭连接: %s", conn.ID)
  71. go func(c *WebSocketConnection) {
  72. m.unregister <- c
  73. }(conn)
  74. }
  75. }
  76. m.mutex.RUnlock()
  77. }
  78. }
  79. }
  80. // cleanupStaleConnections 清理超时连接
  81. func (m *WebSocketManager) cleanupStaleConnections() {
  82. ticker := time.NewTicker(30 * time.Second)
  83. defer ticker.Stop()
  84. for range ticker.C {
  85. m.mutex.Lock()
  86. now := time.Now()
  87. for id, conn := range m.connections {
  88. // 如果连接超过5分钟没有发送数据,则关闭
  89. if now.Sub(conn.LastSendTime) > 5*time.Minute {
  90. log.Printf("清理超时WebSocket连接: %s", id)
  91. delete(m.connections, id)
  92. conn.Conn.Close()
  93. close(conn.SendChan)
  94. }
  95. }
  96. m.mutex.Unlock()
  97. }
  98. }
  99. // Register 注册新连接
  100. func (m *WebSocketManager) Register(id string, conn *websocket.Conn) *WebSocketConnection {
  101. wsConn := &WebSocketConnection{
  102. ID: id,
  103. Conn: conn,
  104. LastSendTime: time.Now(),
  105. IsFirstSend: true,
  106. SendChan: make(chan []byte, 10),
  107. }
  108. // 启动发送协程
  109. go wsConn.writePump()
  110. m.register <- wsConn
  111. return wsConn
  112. }
  113. // Unregister 注销连接
  114. func (m *WebSocketManager) Unregister(id string) {
  115. m.mutex.RLock()
  116. if conn, exists := m.connections[id]; exists {
  117. m.unregister <- conn
  118. }
  119. m.mutex.RUnlock()
  120. }
  121. // GetConnection 获取连接
  122. func (m *WebSocketManager) GetConnection(id string) (*WebSocketConnection, bool) {
  123. m.mutex.RLock()
  124. defer m.mutex.RUnlock()
  125. conn, exists := m.connections[id]
  126. return conn, exists
  127. }
  128. // Broadcast 广播消息到所有连接
  129. func (m *WebSocketManager) Broadcast(data interface{}) error {
  130. message, err := json.Marshal(data)
  131. if err != nil {
  132. return err
  133. }
  134. m.broadcast <- message
  135. return nil
  136. }
  137. // BroadcastToClient 发送消息到指定客户端
  138. func (m *WebSocketManager) BroadcastToClient(id string, data interface{}) error {
  139. m.mutex.RLock()
  140. conn, exists := m.connections[id]
  141. m.mutex.RUnlock()
  142. if !exists {
  143. return nil
  144. }
  145. message, err := json.Marshal(data)
  146. if err != nil {
  147. return err
  148. }
  149. select {
  150. case conn.SendChan <- message:
  151. conn.LastSendTime = time.Now()
  152. default:
  153. return nil
  154. }
  155. return nil
  156. }
  157. // writePump 写入数据到WebSocket连接
  158. func (c *WebSocketConnection) writePump() {
  159. defer func() {
  160. c.Conn.Close()
  161. GlobalWSManager.Unregister(c.ID)
  162. }()
  163. for {
  164. select {
  165. case message, ok := <-c.SendChan:
  166. if !ok {
  167. return
  168. }
  169. c.mu.Lock()
  170. err := c.Conn.WriteMessage(websocket.TextMessage, message)
  171. c.mu.Unlock()
  172. if err != nil {
  173. log.Printf("WebSocket发送消息失败 %s: %v", c.ID, err)
  174. return
  175. }
  176. }
  177. }
  178. }
  179. // UpdateLastDataHash 更新最后发送的数据哈希
  180. func (c *WebSocketConnection) UpdateLastDataHash(hash string) {
  181. c.mu.Lock()
  182. defer c.mu.Unlock()
  183. c.LastDataHash = hash
  184. }
  185. // GetLastDataHash 获取最后发送的数据哈希
  186. func (c *WebSocketConnection) GetLastDataHash() string {
  187. c.mu.Lock()
  188. defer c.mu.Unlock()
  189. return c.LastDataHash
  190. }
  191. // SetIsFirstSend 设置是否首次发送
  192. func (c *WebSocketConnection) SetIsFirstSend(isFirst bool) {
  193. c.mu.Lock()
  194. defer c.mu.Unlock()
  195. c.IsFirstSend = isFirst
  196. }
  197. // GetIsFirstSend 获取是否首次发送
  198. func (c *WebSocketConnection) GetIsFirstSend() bool {
  199. c.mu.Lock()
  200. defer c.mu.Unlock()
  201. return c.IsFirstSend
  202. }