package main import ( "flag" "fmt" "log" "net" "net/url" "os" "os/signal" "strconv" "time" "github.com/gorilla/websocket" ) func main() { addr := flag.String("addr", "localhost:9080", "http service address") querySocket := flag.String("socket", "", "Path to a unix domain socket for the HTTP server") backlogLimit := flag.Int("n", -1, "Limit the backlog length, defaults to no limit (-1)") flag.Parse() interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) var d *websocket.Dialer u := url.URL{Scheme: "ws", Host: *addr, // ignored in case of -socket; see the Dialer below Path: "/ws", } q := u.Query() if *backlogLimit >= 0 { q.Set("l", strconv.Itoa(*backlogLimit)) } u.RawQuery = q.Encode() if *querySocket != "" { d = &websocket.Dialer{ NetDial: func(network, addr string) (net.Conn, error) { return net.Dial("unix", *querySocket) }, HandshakeTimeout: 45 * time.Second, // same as DefaultDialer } log.Printf("connecting to %s", *querySocket) } else { d = websocket.DefaultDialer log.Printf("connecting to %s", *addr) } c, _, err := d.Dial(u.String(), nil) if err != nil { log.Fatal("dial:", err) } defer c.Close() log.Println("connected!", u.String()) done := make(chan struct{}) go func() { defer close(done) for { _, message, err := c.ReadMessage() if err != nil { log.Println("close:", err) return } fmt.Println(string(message)) } }() for { select { case <-done: return case <-interrupt: log.Println("interrupt") // Cleanly close the connection by sending a close message and then waiting (with timeout) for the // server to close the connection. err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) if err != nil { log.Println("write close:", err) return } select { case <-done: log.Println("Successfully close") case <-time.After(1 * time.Second): log.Println("Forced close") } return } } }