Golang 官方認可的 websocket 庫-gorilla/websocket
推薦理由
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:
- 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 marshal function.
- 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 非併發安全,使用時注意不要多個協程併發呼叫。
參考資料
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- golang開發 gorilla websocket的使用GolangWeb
- gorilla websocket簡易介紹GoWeb
- golang programming language study methods websocketGolangWeb
- WebSocket的故事(一)—— WebSocket的由來Web
- 用 Golang 實現百萬級 Websocket 服務GolangWeb
- [開源] Golang 實現的分散式 WebSocket 微服務Golang分散式Web微服務
- 基於 golang + vue + websocket 開發的聊天室GolangVueWeb
- WebSocket於HTTP 、WebSocket與Socket的區別WebHTTP
- websocketWeb
- WebSocket的SSL認證失敗問題記錄Web
- 用 golang 去實現類似 swoole 的 websocket 服務 ?GolangWeb
- 【譯】WebSocket協議第三章——WebSocket網址(WebSocket URIs)Web協議
- 深入淺出Websocket(一)Websocket協議Web協議
- go websocketGoWeb
- WebSocket 用法Web
- FastAPI WebSocketASTAPIWeb
- WebSocket APIWebAPI
- WebSocket 握手Web
- websocket and fastapiWebASTAPI
- 基於 Golang/WebSocket/Canvas/Protobuf 的線上匿名交流遊戲GolangWebCanvas遊戲
- WebSocket的故事(六)—— Springboot中,實現更靈活的WebSocketWebSpring Boot
- WebSocket原理與實踐(二)---WebSocket協議Web協議
- 基於WebSocket的modbus通訊(三)- websocket和串列埠Web串列埠
- golang寫的即時通訊伺服器gim,支援TCP,WebSocketGolang伺服器TCPWeb
- 基於websocket與nodejs-websocket的簡單聊天室WebNodeJS
- 深入淺出Websocket(二)分散式Websocket叢集Web分散式
- Nginx 支援websocket的配置NginxWeb
- 簡單的websocket demoWeb
- WebSocket的調研分析Web
- Sanic WebSocket 使用Web
- websocket及延展Web
- webSocket筆記Web筆記
- WebSocket 入門Web
- Spring Boot WebSocketSpring BootWeb
- websocket初次使用Web
- SpringBoot配置WebSocketSpring BootWeb
- websocket與RPCWebRPC
- WebSocket協議Web協議