Golang Cafe #47 まとめ WebSocketを試す。

2014/09/014に開催された「Golang Cafe #47」についてのまとめです。
今回はGo言語でWebSocket(サーバー側)を試してみる会となりました。


Go言語のWebSocket実装で有名どころ(検索でヒットしそうなの)は、このあたりでしょうか。

ほかにもGoDocで検索するとたくさん出てきます。


その中なら準標準パケージ(?)のgo.net/websocketを試してみることにしました。

準備

お約束ですが、go getしておきます。

$ go get code.google.com/p/go.net/websocket
サンプル

クライアント側は、昨年前半にHTML5のお勉強会をしていた時のサンプルを使用します。HTML5のお勉強会の時はサーバー側はnode.jsでwsモジュールを使用していました。
今回はその部分をGoに置き換えます。
こちらの中から
sample01.html、sample01.js、sample.css
を使用します。
sample01.jsの15行目辺りを

ws = new WebSocket('ws://localhost:8080/echo');

に修正してGoのソースコードと同じディレクトリに配置します。


WebSocketサーバー側の実装はこちらを参考にします。

func echoHandler(ws *websocket.Conn) {
    io.Copy(ws, ws)
}

func main() {
    http.Handle("/echo", websocket.Handler(echoHandler))
    http.Handle("/", http.FileServer(http.Dir(".")))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
}

クライアントのページを読み込み、接続ボタンでWebSocketサーバーに接続し、送信ボタンをクリックするとテキストボックスに入力された文字列がエコーバックされるだけのサンプルです。


上記サンプルでは、WebSocketで接続された際、echoHandler関数が呼び出されます。
引数にはwebsocket.Connが指定されているので、このコネクションに対して、Read、Writeするだけです。
読み書きする方法、内容については個々で調べてください。


ただ、気をつけなくてはならないのは、echoHandler関数を抜けた時点でコネクションが破棄されてしまうということです。
goroutine等で処理していても同じみたいです。


サンプルコードのio.Copyの実装を確認してもらえば分かると思いますが、forで無限ループしています。
独自の実装をする場合もコネクションを破棄しないようにする必要があります。
この辺りはnode.jsのwsのモジュールのon使った書き方の方が直感的で分かりやすいかも知れません。
(別にGoでも同じように実装できると思いますが)


Go言語のWebSocketに限ったことではないですが、まだすべてのブラウザがWebSocketをサポートしているわけではないし、ネットワーク的に使用できない場合もあると思うので、go-socket.ioなるものを試してみるのもいいかもしれません。
ただ、yosuke-furukawaの記事にあるようにパフォーマンスはまだよろしくないようです。
(後に試してみたいと思います)


というわけでWebSocket使いたければ、そこだけnode.jsでもいいんじゃないの?という気もしてきました。