package main import ( "fmt" "log" "net/http" "os" "os/signal" "time" "github.com/gorilla/websocket" ) func main() { // 默认配置,可用环境变量覆盖 baseURL := getenvDefault("SERVER_URL", "wss://api.hifast.biz") userID := getenvDefault("USER_ID", "23") deviceID := getenvDefault("DEVICE_ID", "c76463cff8512722") auth := "dkjw6TCQTBlgreyhjN8u32gP0A6RrQ/V50vf8wjNFwFL9hgKJrOOv+ziS03GCQ/8E0fWUzjc4aCoMcVMzUN8vR7CwqR45HbtogoT9iNoElW9rgzpQNbwQ4BHK/Q25WvcgdrhfRzE19nPqUTOcN+4iY6NmeiwHEMLBTzDEeu8wGn/yjVLRMCyh5QJuQizllbrDR5LuTiNEcdSdBSx9cFZYtnJIIyi1b60BZYo4lIyRADCH6smTsLDhoZG0nJvJw3C0XCGvf0jC/4d4u40IvbzKOm1TBSK0lgOzNjvkSfS/DJibAi4l7qNTYmFlQ1wp+iW1MNllqd+OtSavZYoajoZGA==" // 拼接完整 WS 地址 wsURL := fmt.Sprintf("%s/v1/app/ws/%s/%s", baseURL, userID, deviceID) // 自定义 header(包含 Authorization) header := http.Header{} header.Set("Authorization", auth) // 建立连接 dialer := websocket.Dialer{ HandshakeTimeout: 10 * time.Second, } conn, _, err := dialer.Dial(wsURL, header) if err != nil { log.Fatalf("dial error: %v", err) } defer conn.Close() log.Println("connected to", wsURL) // 优雅退出 interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) // 心跳:定时发送 "ping" ticker := time.NewTicker(25 * time.Second) defer ticker.Stop() // 读协程 done := make(chan struct{}) go func() { defer close(done) for { mt, msg, err := conn.ReadMessage() if err != nil { log.Printf("read error: %v", err) return } log.Printf("recv [%d]: %s", mt, string(msg)) } }() // 连接成功后先发一个 "ping" if err := conn.WriteMessage(websocket.TextMessage, []byte("ping")); err != nil { log.Printf("write ping error: %v", err) } for { select { case <-done: return case <-ticker.C: if err := conn.WriteMessage(websocket.TextMessage, []byte("ping")); err != nil { log.Printf("write heartbeat error: %v", err) return } log.Printf("sent heartbeat ping") case <-interrupt: log.Println("interrupt, closing...") _ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) return } } } func getenvDefault(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def }