package client import ( "net" "sync" "time" "github.com/noahlann/nnet/pkg/client" ) // udpClient UDP客户端实现 type udpClient struct { config *client.Config conn *net.UDPConn serverAddr *net.UDPAddr mu sync.RWMutex connected bool } // NewUDPClient 创建UDP客户端 func NewUDPClient(config *client.Config) client.Client { if config == nil { config = client.DefaultConfig() } return &udpClient{ config: config, connected: false, } } // Connect 连接服务器 func (c *udpClient) Connect() error { c.mu.Lock() defer c.mu.Unlock() if c.connected { return nil } // 解析地址 addr := c.config.Addr if len(addr) > 6 && addr[:6] == "udp://" { addr = addr[6:] } // 解析服务器地址 serverAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return client.NewErrorf("failed to resolve UDP address: %v", err) } // 创建UDP连接 conn, err := net.DialUDP("udp", nil, serverAddr) if err != nil { return client.NewErrorf("failed to dial UDP: %v", err) } c.conn = conn c.serverAddr = serverAddr c.connected = true return nil } // Disconnect 断开连接 func (c *udpClient) Disconnect() error { c.mu.Lock() defer c.mu.Unlock() if !c.connected { return nil } if c.conn != nil { c.conn.Close() c.conn = nil } c.connected = false return nil } // Send 发送数据 func (c *udpClient) Send(data []byte) error { c.mu.RLock() defer c.mu.RUnlock() if !c.connected || c.conn == nil { return client.NewError("not connected") } _, err := c.conn.Write(data) return err } // Receive 接收数据 func (c *udpClient) Receive() ([]byte, error) { c.mu.RLock() defer c.mu.RUnlock() if !c.connected || c.conn == nil { return nil, client.NewError("not connected") } // 设置读取超时 if c.config.ReadTimeout > 0 { c.conn.SetReadDeadline(time.Now().Add(c.config.ReadTimeout)) } buffer := make([]byte, 4096) n, err := c.conn.Read(buffer) if err != nil { return nil, err } result := make([]byte, n) copy(result, buffer[:n]) return result, nil } // Request 请求-响应(带超时) func (c *udpClient) Request(data []byte, timeout time.Duration) ([]byte, error) { // 发送请求 if err := c.Send(data); err != nil { return nil, err } // 设置读取超时 oldTimeout := c.config.ReadTimeout c.config.ReadTimeout = timeout defer func() { c.config.ReadTimeout = oldTimeout }() // 接收响应 return c.Receive() } // IsConnected 检查是否已连接 func (c *udpClient) IsConnected() bool { c.mu.RLock() defer c.mu.RUnlock() return c.connected } // Close 关闭客户端 func (c *udpClient) Close() error { return c.Disconnect() }