ページ

2009年12月10日

WebSocketでChatを作ってみた

MacにChromeを入れたことだし、HTML5のWebSocketでChatを作ってみました。サーバがgolangで作っています。クライアント側のコードは、こんな感じです。
<html>
<head><title>Web Socket Chat</title></head>
<body>
<script>
var ws = new WebSocket("ws://127.0.0.1:1972/chat");
ws.onopen = function() {
};

ws.onmessage = function(message) {
var txtNode = document.createTextNode(message.data);
var brNode = document.createElement('br');
var cnode = document.getElementById("content");
cnode.appendChild(txtNode);
cnode.appendChild(brNode);
};
</script>
<h1>Web Socket Chat</h1>
<div id="content">
</div>
<input id="message" type="text" onChange="javascript:ws.send(this.value);this.value='';"/>
</body>
</html>



ポイントは赤い文字の部分で、簡単にWebSocketのオブジェクトを制御できます。
サーバサイドはgolangでこんな感じ。まあ、いつぞやのチャットサーバを書き換えたものです。


package main

import (
"http";
"log";
"bytes";
"fmt";
"os";
"websocket";
)

const MAXREQSIZE = 0x10000;

func startServer() {
// initialize
queue := make(chan string);
listen_chan := make(map [*websocket.Conn] chan string);

go func() {
for {
mesg := <- queue;
for _, c := range listen_chan {
c <- mesg;
}
}
}();

read := func(ws *websocket.Conn, errChan chan os.Error) {
buf := make([]byte, MAXREQSIZE);
for {
fmt.Print("Reading...\n");
l, err := ws.Read(buf);
if err != nil {
fmt.Print(err);
errChan <- err;
return;
}
fmt.Printf("received: %s¥n", buf[0:l]);
queue <- string(buf[0:l]);
}
};

write := func(ws *websocket.Conn, mesgChan chan string, errChan chan os.Error) {
for {
mesg := <- mesgChan;
_, err := ws.Write(bytes.NewBufferString(mesg).Bytes());
if err != nil {
errChan <- err;
return;
}
}
};

OnConnected := func(ws *websocket.Conn) {
fmt.Printf("Connection Opend\n");
mesgChan := make(chan string);
listen_chan[ws] = mesgChan;
errChan := make(chan os.Error);

go read(ws, errChan);
go write(ws, mesgChan, errChan);
err := <-errChan;
fmt.Printf("Done%d\n", err);
listen_chan[ws] = nil, false;
};

// http handlers
http.Handle("/", http.HandlerFunc(func(c *http.Conn, req *http.Request) {
path := req.URL.Path;
log.Stdout("Request URL: " + path);
http.ServeFile(c, req, "." + path);
}));

http.Handle("/chat", websocket.Handler(OnConnected));

err := http.ListenAndServe(":1972", nil);
if err != nil {
log.Stderr(err.String());
return;
}
}

func main() {
log.Stdout("starting server...");
startServer()
}





これを実行して、Chromeを複数動かして、どれかで何かを打ち込むと、他のブラウザに打ち込んだものが出現します

0 件のコメント: