推荐理由
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/netRFC 6455 FeaturesPasses Autobahn Test SuiteYesNoReceive fragmented messageYesNo, see note 1Send close messageYesNoSend pings and receive pongsYesNoGet the type of a received data messageYesYes, see note 2Other FeaturesCompression ExtensionsExperimentalNoRead message using io.ReaderYesNo, see note 3Write message using io.WriteCloserYesNo, see note 3Notes:
Large messages are fragmented in Chrome's new WebSocket implementation.
The application can get the type of a received data message by implementing a Codec marshalfunction.
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