项目地址:
https://github.com/gorilla/websocket
websocket 在线调试工具:
https://www.lddgo.net/network/websocket
示例代码:
目录结构:
|—— gorilla/ // 根目录 ****|—— client/ ********|—— main.go // 客户端 ****|—— server/ ********|—— main.go // 服务端
server/main.go:
package main import ( "context" "fmt" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "net/http" "os" "os/signal" "syscall" "time" ) const ( Address = "localhost:8091" ) func checkToken(token string) bool { return true } func Chat(ctx *gin.Context) { token := ctx.GetHeader("token") // 校验 token 是否合法 islegal := checkToken(token) conn, err := (&websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return islegal }, }).Upgrade(ctx.Writer, ctx.Request, nil) if err != nil { fmt.Println("upgrade error:", err) return } // 发送消息 go func() { for { err := conn.WriteMessage(websocket.TextMessage, []byte("hello from server!")) if err != nil { fmt.Println(err.Error()) return } time.Sleep(3 * time.Second) } }() // 接收消息 for { _, data, err := conn.ReadMessage() if err != nil { fmt.Println(err.Error()) return } fmt.Println("message from client:", string(data)) } } func main() { quit := make(chan os.Signal, 1) // 退出信号 signal.Notify(quit, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) r := gin.Default() r.GET("/chat", Chat) srv := &http.Server{ Addr: Address, Handler: r, } go shutdown(quit, srv) fmt.Printf("server running at:%s \n", Address) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { panic(err) } } func shutdown(quit chan os.Signal, srv *http.Server) { <-quit ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() fmt.Println("server shutdown...") if err := srv.Shutdown(ctx); err != nil { fmt.Println("shutdown error:", err) } os.Exit(0) }
启动 server/main.go(略)
client/main.go:
package main import ( "fmt" "github.com/gorilla/websocket" "net/http" "os" "os/signal" "syscall" "time" ) var msgChan = make(chan string) func wsClient() { quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) token := "" socketUrl := "ws://localhost:8091" + "/chat" header := http.Header{} header.Add("token", token) conn, _, err := websocket.DefaultDialer.Dial(socketUrl, header) if err != nil { panic(err) } defer conn.Close() // 发送消息 go func() { for { select { case msg := <-msgChan: err := conn.WriteMessage(websocket.TextMessage, []byte(msg)) if err != nil { fmt.Println("write error:", err) } case <-quit: fmt.Println("control + c pressed!") err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) if err != nil { fmt.Println("send close message error:", err) os.Exit(0) } if err := conn.Close(); err != nil { fmt.Println("conn close error:", err) os.Exit(0) } os.Exit(0) } } }() // 接收消息 for { _, msg, err := conn.ReadMessage() if err != nil { fmt.Println("Error in receive:", err) return } fmt.Println("message from server:", string(msg)) } } func main() { go wsClient() // 将要发送到服务端的消息传递到消息管道 for i := 0; i < 3; i++ { msgChan <- "hello from client!" time.Sleep(3 * time.Second) } select {} }
启动 client/main.go(略)
文档更新时间: 2024-04-20 10:57 作者:lee