WebSocketをGoで触ってみた

More than 3 years have passed since last update.


WebSocket?

以下のスライドでどういうものかは学びました。

http://www.slideshare.net/You_Kinjoh/websocket-10621887


Goで実装を試す

シンプルにechoサーバを実装すると以下のようになります。


main.go

package main

import (
"code.google.com/p/go.net/websocket"
"io"
"net/http"
)

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

func main() {

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

}



index.html


<html>
<head>
<title>websocket sample</title>
<script type="text/javascript">
// var wsUri = "ws://echo.websocket.org/";
var wsUri = "ws://localhost:9999/echo";

var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}

function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}

function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("websocketにメッセージを送信");
}

function onClose(evt) {

writeToScreen("DISCONNECTED");
}

function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + jsonData.Msg+'</span>');
websocket.close();
}

function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}

function doSend(message) {
websocket.send(message);
}

function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}

window.addEventListener("load", init, false);
</script>
</head>
<body>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>


デフォルトではクロスドメイン通信は許可されていないため、index.htmlをローカルにおいて試すと以下の様なエラーが出ます

WebSocket connection to 'ws://localhost:9999/echo' failed: Unexpected response code: 403

以下のように変更すればクロスドメイン通信できるようになります。


変更箇所

http.Handle("/echo", websocket.Handler(echoHandler))



変更内容

http.HandleFunc("/echo",

func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{Handler: websocket.Handler(echoHandler)}
s.ServeHTTP(w, req)
})


JSONで通信したい場合


main.go



package main

import (
"code.google.com/p/go.net/websocket"
"log"
"net/http"
)

func echoHandler(ws *websocket.Conn) {

type T struct {
Msg string
Count float64
}

// receive JSON type T
var data T
websocket.JSON.Receive(ws, &data)

log.Printf("data=%#v\n", data)

// send JSON type T
websocket.JSON.Send(ws, data)
}

func main() {

http.Handle("/", http.FileServer(http.Dir("./")))
http.HandleFunc("/echo",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{Handler: websocket.Handler(echoHandler)}
s.ServeHTTP(w, req)
})

if err := http.ListenAndServe(":9999", nil); err != nil {
panic("ListenAndServe: " + err.Error())
}

}



index.html


<html>
<head>
<title>websocket sample</title>
<script type="text/javascript">
// var wsUri = "ws://echo.websocket.org/";
var wsUri = "ws://localhost:9999/echo";

var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}

function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}

function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("websocketにメッセージを送信",Math.random());
}

function onClose(evt) {

writeToScreen("DISCONNECTED");
}

function onMessage(evt) {

var jsonData=JSON.parse(evt.data)

writeToScreen('<span style="color: blue;">RESPONSE: ' + jsonData.Msg+",no:"+jsonData.Count+'</span>');
websocket.close();
}

function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}

function doSend(message,number) {

writeToScreen("SENT: " + message+",no: "+number);
var jsonData={
Msg:message,
Count:number
}

websocket.send(JSON.stringify(jsonData));
}

function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}

window.addEventListener("load", init, false);
</script>
</head>
<body>

<h2>WebSocket Test</h2>
<div id="output"></div>

</body>
</html>



参考

https://github.com/golang-samples/websocket

http://stackoverflow.com/questions/19708330/serving-a-websocket-in-go