WebSocketでバイナリを送受信してみた

Firefox11になってとっくにWebSocketのベンダープレフィックスとれてたし、
バイナリデータの送受信の辺りがどうなってるか確認してみた。

確認したブラウザはFirefox11.0とGoogle Chrome18.0.1025.162。

サーバ側


node.jsで実装する。
httpサーバ用にconnectを使って、WebSocketサーバはWebSocket-Nodeを使う。

それぞれnpm install connect、npm install websocketでモジュール入れる。

サーバ側のコードは次の通り。

// http server
var connect = require('connect');
var httpServer = connect()
.use(connect.static(__dirname + '/webroot'))
.listen(1234);

// WebSocket Server
var WebSocketServer = require('websocket').server;
var wsServer = new WebSocketServer({
    httpServer : httpServer,
    autoAcceptConnections : true
});

// クライアント接続イベント
wsServer.on('connect', function(client) {
    // クライアントからのメッセージ受信イベント
    client.on('message', function(message) {
        if (message.type === 'utf8') {
            // 文字列だったら文字列としてそのまま送信
            client.sendUTF(message.utf8Data);
        } else if (message.type === 'binary') {
            // バイナリだったらバイナリとしてそのまま送信
            client.sendBytes(message.binaryData);
        } else {
            console.log('nanigashi');
        }   
    }); 
});

クライアント側からメッセージ届いたら、タイプに応じてそのまま返すだけ。

クライアント側


ボタンを押したら固定文字列を送るのと、ファイル参照したらそれを送るようにする。
送ったデータがサーバから送り返されたら、タイプに応じてそれぞれのdivの中に書きだす。
HTML次のとおり。

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>WebSocket Test</title>
    </head>
    <body>
        <input id="sendText" type="button" value="文字列を送る" />
        <input id="image" name="image" type="file" />
        <!-- 文字列受信ログ -->
        <div id="messages"></div>
        <!-- 画像受信ログ -->
        <div id="images"></div>
        <script type="text/javascript" src="index.js"></script>
    </body>
</html>

クライアント側のJavaScript

// URL
URL = window.URL || window.webkitURL;

// document
var doc = document;
        
// WebSocketを開く
var socket = new WebSocket('ws://' + location.host);
        
// messageイベント
socket.addEventListener('message', function(evt) {
    var data = evt.data;
    if (data.constructor === String) {
        // Stringの場合、pタグで追加
        var p = doc.createElement('p');
        p.textContent = data;
        doc.getElementById('messages').appendChild(p);
    } else if (data.constructor === Blob) {
        // Blobの場合、imgタグで追加
        var img = new Image();
        img.src = URL.createObjectURL(data);
        doc.getElementById('images').appendChild(img);
    } else {
        alert('nanigashi');
    }
}, false);

// 文字列データをサーバに送信
doc.getElementById('sendText')
.addEventListener('click', function(evt) {
    socket.send('test');
}, false);

// fileを参照したらサーバに送信
doc.getElementById('image')
.addEventListener('change', function(evt) {
    var file = evt.target.files[0];
    socket.send(file);
}, false);

結果


FirefoxGoogle Chrome共に送ったバイナリデータを送り返してもらって表示できた。