GolangでWebSocketを使ったHTTPサーバを実装する
はじめに
GolangでWebSocketを使ったHTTPサーバを構築します。
WebSocketの仕様は RFC6455 で定められています。Webアプリケーションにおいて、双方向通信を実現するための技術規格です。Ajaxではブラウザからサーバにデータの送信要求を出す手段でした。WebSocketではサーバからのデータをプッシュすることが可能になります。
GolangでWebSocketを扱うには golang.org/x/net/WebSocket パッケージを用いることができます。他にも存在します。
シンプルに実装することができて、type Handler func(*Conn)
の func(*Conn)
を実装すればよいです。
実装
package main import ( "fmt" "log" "math/rand" "net/http" "strconv" "time" "golang.org/x/net/WebSocket" ) var dataCh chan Data type Data struct { MyData string `json:"myData"` } func main() { dataCh = make(chan Data, 1) http.HandleFunc("/", plotHandle) http.Handle("/data", WebSocket.Handler(dataHandler)) err := http.ListenAndServe(":8888", nil) if err != nil { log.Fatal(err) } } func plotHandle(w http.ResponseWriter, r *http.Request) { go func() { for { dataCh <- Data{strconv.Itoa(rand.Int())} time.Sleep(500 * time.Millisecond) } }() fmt.Fprintf(w, page) } func dataHandler(ws *WebSocket.Conn) { for data := range dataCh { err := WebSocket.JSON.Send(ws, data) if err != nil { log.Printf("error sending data: %v\n", err) return } } } const page = ` <html> <head> <title>Hello WebSocket</title> <script type="text/javascript"> var sock = null; var myData = ""; function update() { var p1 = document.getElementById("my-data-plot"); p1.innerHTML = myData; }; window.onload = function() { sock = new WebSocket("ws://"+location.host+"/data"); sock.onmessage = function(event) { var data = JSON.parse(event.data); myData = data.myData; update(); }; }; </script> </head> <body> <div id="header"> <h1>Hello WebSocket</h1> </div> <div id="content"> <div id="my-data-plot"></div> </div> </body> </html> `
上記の実装はデータの送信にチャネルを用いていますが、以下のようにチャネルを使わなくても問題ないです。
WebSocket.JSON.Send(ws, Data{strconv.Itoa(rand.Int())})
ブラウザで確認すると以下のように数字列が更新されていくのが分かります。wscat などを使って確認することもできます。
Tips
WebSocketそのものについては以下がわかりやすそうです。