package network import ( "encoding/json" "log" "sync" "time" "github.com/gorilla/websocket" ) type ClientConfig struct { ServerURL string SendInterval time.Duration BufferSize int } type WSClient struct { config ClientConfig conn *websocket.Conn sendChan chan Packet mu sync.Mutex isConnected bool stopChan chan struct{} } func NewWSClient(cfg ClientConfig) *WSClient { if cfg.BufferSize == 0 { cfg.BufferSize = 100 } return &WSClient{ config: cfg, sendChan: make(chan Packet, cfg.BufferSize), stopChan: make(chan struct{}), } } func (c *WSClient) Start() { go c.connectionLoop() go c.sendLoop() } func (c *WSClient) SendQueue(packet Packet) { select { case c.sendChan <- packet: default: log.Printf("[网络] 发送队列已满,丢弃消息: %s", packet.Type) } } func (c *WSClient) Stop() { close(c.stopChan) if c.conn != nil { c.conn.Close() } } func (c *WSClient) sendLoop() { for { select { case <-c.stopChan: return case packet := <-c.sendChan: c.sendRaw(packet) } } } func (c *WSClient) sendRaw(packet Packet) { c.mu.Lock() defer c.mu.Unlock() if !c.isConnected || c.conn == nil { log.Printf("[网络] 无连接,无法发送消息: %s", packet.Type) return } c.conn.SetWriteDeadline(time.Now().Add(5 * time.Second)) payload, _ := json.Marshal(packet) if err := c.conn.WriteMessage(websocket.TextMessage, payload); err != nil { log.Printf("[网络] 发送消息失败: %v", err) c.isConnected = false } } func (c *WSClient) connectionLoop() { for { select { case <-c.stopChan: return default: if !c.isConnected { if err := c.connect(); err != nil { log.Printf("[网络] 连接 %s 失败: %v. 5秒后重试...", c.config.ServerURL, err) time.Sleep(5 * time.Second) continue } } _, _, err := c.conn.ReadMessage() if err != nil { log.Printf("[网络] 连接断开: %v", err) c.closeConn() } // TODO: 处理服务器消息 } } } func (c *WSClient) closeConn() { c.mu.Lock() defer c.mu.Unlock() if c.conn != nil { c.conn.Close() c.conn = nil } c.isConnected = false } func (c *WSClient) connect() any { c.mu.Lock() defer c.mu.Unlock() conn, _, err := websocket.DefaultDialer.Dial(c.config.ServerURL, nil) if err != nil { return err } c.conn = conn c.isConnected = true log.Printf("[网络] 成功连接到服务器: %s", c.config.ServerURL) return nil }