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

共 6281字,需浏览 13分钟

 ·

2021-07-18 14:17

推荐理由

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/gorillagolang.org/x/net



RFC 6455 Features
Passes Autobahn Test SuiteYesNo
Receive fragmented messageYesNo, see note 1
Send close messageYesNo
Send pings and receive pongsYesNo
Get the type of a received data messageYesYes, see note 2
Other Features
Compression ExtensionsExperimentalNo
Read message using io.ReaderYesNo, see note 3
Write message using io.WriteCloserYesNo, 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 main

import (
 "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:
   return
        case t := <-ticker.C:
            // 向服务端发送message
   err := 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 main

import (
 "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 {
        // 接收客户端message
  mt, message, err := c.ReadMessage()
  if err != nil {
   log.Println("read:", err)
   break
  }
        log.Printf("recv: %s", message)
        // 向客户端发送message
  err = 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 的大家族哟~







浏览 41
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报