Go WebSocket 簡單使用
WebSocket在 HTML5 遊戲和網頁訊息推送都使用比較多。WebSocket 是 HTML5 的重要特性,它實現了基於瀏覽器的遠端socket,它使瀏覽器和伺服器可以進行全雙工通訊。
WebSocket 具體的特性和 http 的區別這裡就不多說,可以去自己查一下。
Go 官方沒有提供對 WebSocket 的支援,必須選擇第三方提供的包。《Go Web 程式設計》一書中的例子使用了golang.org/x/net
下的websocket
包。 另外一個使用比較多的是gorilla/websocket
,我接觸的專案是使用的這個。下面我就以gorilla/websocket
來寫一個簡單的通訊示例。
gorilla/websocket
的資料參考:
GitHub:https://github.com/gorilla/websocket
Doc:https://godoc.org/github.com/gorilla/websocket
gorilla/websocket 介面簡述
Upgrader 用於升級 http 請求,把 http 請求升級為長連線的 WebSocket。結構如下:
type Upgrader struct { // 指定升級 websocket 握手完成的超時時間 HandshakeTimeout time.Duration // 指定 io 操作的快取大小,如果不指定就會自動分配。 ReadBufferSize, WriteBufferSize int // 寫資料操作的快取池,如果沒有設定值,write buffers 將會分配到連結生命週期裡。 WriteBufferPool BufferPool //按順序指定服務支援的協議,如值存在,則服務會從第一個開始匹配客戶端的協議。 Subprotocols []string // 指定 http 的錯誤響應函式,如果沒有設定 Error 則,會生成 http.Error 的錯誤響應。 Error func(w http.ResponseWriter, r *http.Request, status int, reason error) // 請求檢查函式,用於統一的連結檢查,以防止跨站點請求偽造。如果不檢查,就設定一個返回值為true的函式。 // 如果請求Origin標頭可以接受,CheckOrigin將返回true。 如果CheckOrigin為nil,則使用安全預設值:如果Origin請求頭存在且原始主機不等於請求主機頭,則返回false CheckOrigin func(r *http.Request) bool // EnableCompression 指定伺服器是否應嘗試協商每個郵件壓縮(RFC 7692)。 // 將此值設定為true並不能保證將支援壓縮。 // 目前僅支援“無上下文接管”模式 EnableCompression bool }
func (*Upgrader)Upgrade
Upgrade 函式將 http 升級到 WebSocket 協議。定義如下:
// responseHeader包含在對客戶端升級請求的響應中。 // 使用responseHeader指定cookie(Set-Cookie)和應用程式協商的子協議(Sec-WebSocket-Protocol)。 // 如果升級失敗,則升級將使用HTTP錯誤響應回覆客戶端 // 返回一個 Conn 指標,拿到他後,可使用 Conn 讀寫資料與客戶端通訊。 func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error)
使用例項
type WsServer struct { ...... upgrade*websocket.Upgrader } func NewWsServer() *WsServer { ws.upgrade = &websocket.Upgrader{ ReadBufferSize:4096, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { if r.Method != "GET" { fmt.Println("method is not GET") return false } if r.URL.Path != "/ws" { fmt.Println("path error") return false } return true }, } return ws } func (self *WsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...... conn, err := self.upgrade.Upgrade(w, r, nil) if err != nil { fmt.Println("websocket error:", err) return } fmt.Println("client connect :", conn.RemoteAddr()) go self.connHandle(conn) }
WebSocket 客戶端
- 更新中