当前位置: 代码迷 >> 综合 >> 【GoCN酷Go推荐】Golang官方认可的websocket库-gorilla/websocket
  详细解决方案

【GoCN酷Go推荐】Golang官方认可的websocket库-gorilla/websocket

热度:38   发布时间:2023-12-06 01:08:18.0

推荐理由

Golang官方标准库实现的websocket在功能上有些欠缺,本次介绍的gorilla/websocket库,是Gorilla出品的速度快、质量高,并且被广泛使用的websocket库,很好的弥补了标准库功能上的欠缺。另外Gorilla Web toolkit包含多个实用的HTTP应用相关的工具库,感兴趣可以到官网主页https://www.gorillatoolkit.org自取。

功能介绍

gorilla/websocket库是 RFC 6455 定义的websocket协议的一种实现,在数据收发方面,提供Data Messages、Control Messages两类message粒度的读写API;性能方面,提供Buffers和Compression的相关配置选项;安全方面,可通过CheckOrigin来控制是否支持跨域。

gorilla/websocket库和官方实现的对比

摘自 gorilla GitHub 主页


github.com/gorilla golang.org/x/net



RFC 6455 Features
Passes Autobahn Test Suite Yes No
Receive fragmented message Yes No, see note 1
Send close message Yes No
Send pings and receive pongs Yes No
Get the type of a received data message Yes Yes, see note 2
Other Features
Compression Extensions Experimental No
Read message using io.Reader Yes No, see note 3
Write message using io.WriteCloser Yes No, see note 3

Notes:

  1. Large messages are fragmented in Chrome's new WebSocket implementation.

  2. The application can get the type of a received data message by implementing a Codec marshalfunction.

  3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries. Read returns when the input buffer is full or a frame boundary is encountered. Each call to Write sends a single frame message. The Gorilla io.Reader and io.WriteCloser operate on a single WebSocket message.

使用指南

安装

go get github.com/gorilla/websocket

基础示例

下面以一个简单的echo来说明gorilla/websocket库基本使用。

client代码:

package mainimport ("flag""log""net/url""os""os/signal""time""github.com/gorilla/websocket"
)var addr = flag.String("addr", "localhost:8080", "http service address")func main() {flag.Parse()log.SetFlags(0)// 用来接收命令行的终止信号interrupt := make(chan os.Signal, 1)signal.Notify(interrupt, os.Interrupt)// 和服务端建立连接u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}log.Printf("connecting to %s", u.String())c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)if err != nil {log.Fatal("dial:", err)}defer c.Close()done := make(chan struct{})go func() {defer close(done)for {// 从接收服务端message_, message, err := c.ReadMessage()if err != nil {log.Println("read:", err)return}log.Printf("recv: %s", message)}}()ticker := time.NewTicker(time.Second)defer ticker.Stop()for {select {case <-done:returncase t := <-ticker.C:// 向服务端发送messageerr := c.WriteMessage(websocket.TextMessage, []byte(t.String()))if err != nil {log.Println("write:", err)return}case <-interrupt:log.Println("interrupt")// 收到命令行终止信号,通过发送close message关闭连接。err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))if err != nil {log.Println("write close:", err)return}// 收到接收协程完成的信号或者超时,退出select {case <-done:case <-time.After(time.Second):}return}}
}

server代码:

package mainimport ("flag""html/template""log""net/http""github.com/gorilla/websocket"
)var addr = flag.String("addr", "localhost:8080", "http service address")var upgrader = websocket.Upgrader{}func echo(w http.ResponseWriter, r *http.Request) {// 完成和Client HTTP >>> WebSocket的协议升级c, err := upgrader.Upgrade(w, r, nil)if err != nil {log.Print("upgrade:", err)return}defer c.Close()for {// 接收客户端messagemt, message, err := c.ReadMessage()if err != nil {log.Println("read:", err)break}log.Printf("recv: %s", message)// 向客户端发送messageerr = c.WriteMessage(mt, message)if err != nil {log.Println("write:", err)break}}
}func main() {flag.Parse()log.SetFlags(0)http.HandleFunc("/echo", echo)log.Fatal(http.ListenAndServe(*addr, nil))
}

更多示例可以参考 https://github.com/gorilla/websocket/tree/master/examples

总结

gorilla/websocket库是websocket协议的一种实现,相比标准库的实现,封装了协议细节,使用者关注message粒度的API即可,但需要注意message的读写API非并发安全,使用时注意不要多个协程并发调用。

参考资料

  1. https://github.com/gorilla/websocket

还想了解更多吗?

更多请查看:https://github.com/gorilla/websocket

欢迎加入我们GOLANG中国社区:https://gocn.vip/

《酷Go推荐》招募:

各位Gopher同学,最近我们社区打算推出一个类似GoCN每日新闻的新栏目《酷Go推荐》,主要是每周推荐一个库或者好的项目,然后写一点这个库使用方法或者优点之类的,这样可以真正的帮助到大家能够学习到

新的库,并且知道怎么用。

大概规则和每日新闻类似,如果报名人多的话每个人一个月轮到一次,欢迎大家报名!(报名地址:https://wj.qq.com/s2/7734329/3f51)

扫码也可以加入 GoCN 的大家族哟~