どうもです!
書けたり書けなかったりなので、書けるときに書いちゃおうって事で書きます!

最近NodeJSのお勉強をしてまして

まずはWebSocketからということで触ってみました。

っても既にWebSocketのライブラリは存在していて
「node.js websocket」とかでググるとすぐに出てくる、
Socket.IOとかを使うといとも簡単に実装できちゃいます。

なんかあっけないので、WebSocketとはどのようにして通信してる
んだろうってところを見てみました。
因みに、ソケットプログラミングなんてほとんどやったことないです!
なので表現の怪しいところはゆるしてね!

先にも書いたように「node.js websocket」でググると

Socket.IOをつかった似たようなサンプルばかり出てきます。

そこでwebsocketとはから調べどうやらハンドシェイクとやらを経て
データ転送ができるらしいって事を知り、早速ハンドシェイクの実装を
試みました。

まずはテストの為に簡単なwebサーバを実装

server.js

var http = require('http')
    , httpServer = http.createServer()
    , fs = require('fs');

httpServer.on('request', function(req, res) {
    fs.readFile(__dirname + '/public' + req.url.replace(/\/$/, '/index.html'), function(err, data) {
	if (err) {
	    res.writeHead(403);
            res.write('Not found');
            res.end();
	}
	else {
	    res.end(data);
	}
    });
});

httpServer.listen(8080);
server.jsと同階層にあるpublicディレクトリ内に
ファイルがあれば返すってだけの、apacheの
ドキュメントルート的なものを実装してみました。

次にテストに使用するHTMLを用意します。

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="js/index.js"></script>
</head>
<body>
test
</body>
</html>
えー。特に説明する事はありません。

そしてJavaScript

index.js

var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function() {
    console.log("open");
};
ws.onmessage = function(e) {
    console.log("message");
    console.log(e.data);
};
ws.onerror = function() {
    console.log("error");
};
ws.onclose = function() {
    console.log("close");
};
WebSocketで発生するイベントをそれぞれ
コンソールに出力するだけの簡単なものです。

この時点で
node server.js
でサーバー起動してlocalhost:8080に接続してみると
コンソールに「error」「close」が表示されます。
※自分はjsのデバッグはだいたいfirefox+firebugで行ってます

それではまずはハンドシェイクをやってみます。
server.jsで実装したhttpサーバはWebSocketからリクエストを受けると
upgradeイベントが発生します。
その中でハンドシェイクの処理をすればいいわけですね。

って事でserver.jsのhttpServer.listen(8080);の上あたりにハンドシェイクの処理を
追記します。

ハンドシェイク

var crypto = require('crypto');
httpServer.on('upgrade', function(req, socket, head) {
    var acceptBase = req.headers['sec-websocket-key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    var sha1 = crypto.createHash('sha1');
    sha1.update(acceptBase, 'utf8');
    var acceptSha1 = sha1.digest('base64');
    var handshake = ["HTTP/1.1 101 Switching Protocols"
                        , "Upgrade: websocket"
                        , "Connection: Upgrade"
                        , "Sec-WebSocket-Accept: " + acceptSha1
                        , "Sec-WebSocket-Protocol: chat"
                        ].join("\r\n") + "\r\n\r\n";

   socket.write(handshake); 
});
HTTP Upgradeリクエストヘッダに含まれる
sec-websocket-keyの値と「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」(固定)
を結合してsha1→base64エンコードして得た値を含めて返してあげます。

ここでサーバを再起動して一旦確認します。
するとブラウザのコンソールにopenと表示されるはずです
ハンドシェイクが成功しました。

ここまでではまったのは、クライアントに返すデータの最後に改行コード2個
つけるところです。
RFCの通りにやってるはずなのにーって悩んでたら「そういやこれヘッダだ」
ってのに気づき解決

では、いよいよデータ転送なのですが
データ転送部分では主に論理演算ではまりました。
いままで論理演算なんてやったことなかったですもの。

で。。。データ転送についても一気に書いてしまおうと思っていたのですが
正直疲れたので、データ転送部分はもし需要があれば
書こうと思います。。。。