【GoCN酷Go推薦】Golang官方認可的websocket庫-gorilla/websocket
推薦理由
Golang官方標準庫實現(xiàn)的websocket在功能上有些欠缺,本次介紹的gorilla/websocket庫,是Gorilla出品的速度快、質量高,并且被廣泛使用的websocket庫,很好的彌補了標準庫功能上的欠缺。另外Gorilla Web toolkit包含多個實用的HTTP應用相關的工具庫,感興趣可以到官網主頁https://www.gorillatoolkit.org自取。
功能介紹
gorilla/websocket庫是 RFC 6455 定義的websocket協(xié)議的一種實現(xiàn),在數(shù)據(jù)收發(fā)方面,提供Data Messages、Control Messages兩類message粒度的讀寫API;性能方面,提供Buffers和Compression的相關配置選項;安全方面,可通過CheckOrigin來控制是否支持跨域。
gorilla/websocket庫和官方實現(xiàn)的對比
摘自 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:
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 <-done:
return
case t := <-ticker.C:
// 向服務端發(fā)送message
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
if err != nil {
log.Println("write:", err)
return
}
case <-interrupt:
log.Println("interrupt")
// 收到命令行終止信號,通過發(fā)送close message關閉連接。
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("write close:", err)
return
}
// 收到接收協(xié)程完成的信號或者超時,退出
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的協(xié)議升級
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)
// 向客戶端發(fā)送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協(xié)議的一種實現(xiàn),相比標準庫的實現(xiàn),封裝了協(xié)議細節(jié),使用者關注message粒度的API即可,但需要注意message的讀寫API非并發(fā)安全,使用時注意不要多個協(xié)程并發(fā)調用。
參考資料
https://github.com/gorilla/websocket
更多請查看:https://github.com/gorilla/websocket
歡迎加入我們GOLANG中國社區(qū):https://gocn.vip/
《酷Go推薦》招募:
各位Gopher同學,最近我們社區(qū)打算推出一個類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個庫或者好的項目,然后寫一點這個庫使用方法或者優(yōu)點之類的,這樣可以真正的幫助到大家能夠學習到
新的庫,并且知道怎么用。
大概規(guī)則和每日新聞類似,如果報名人多的話每個人一個月輪到一次,歡迎大家報名!(報名地址:https://wj.qq.com/s2/7734329/3f51)
掃碼也可以加入 GoCN 的大家族喲~
