はじめに
「Node.js入門」を少し読みましたので、そのことを少し書きます。基本的なことはネットで見つけることができますので、この記事では「9.4 TCPエコーサーバ・クライアントの実装」のサンプルコードを少し変更して、クライアント間でデータを送受信できるか試してみたことを紹介します。流れとしては、ソースコードを紹介して、試し方を紹介して、試してみた感想になります。
必要なファイルは二つです。server.js
とclient.js
です。(テキストで紹介されているファイル名とは違うファイル名です。)
サーバ側(常駐プロセス)
ソースコードのみの紹介になります。
var net = require('net');
var server = net.createServer();
server.maxConnections = 3;
function Client(socket) {
this.socket = socket;
}
Client.prototype.writeData = function(d) {
var socket = this.socket;
if (socket.writable) {
var key = socket.remoteAddress + ':' + socket.remotePort;
process.stdout.write('[' + key + '] - ' + d);
socket.write('[R] ' + d);
}
};
var clients = {};
function chomp(raw_text)
{
return raw_text.replace(/(\n|\r)+$/,'');
}
server.on('connection', function(socket) {
var status = server.connections + '/' + server.maxConnections;
var key = socket.remoteAddress + ':' + socket.remotePort;
console.log('Connection Start(' + status + ') - ' + key);
clients[key] = new Client(socket);
var data = '';
var newline = /\r\n|\n/;
socket.on('data', function(chunk) {
var k = chunk.toString();
if (newline.test(k)) {
k = chomp(k);
clients['127.0.0.1:' + k].writeData('test data\n');
k ='';
}
});
socket.on('end', function(socket) {
console.log('Connection End(' + status + ') - ' + key);
delete clients[key];
});
});
server.on('close', function() {
console.log('Server Closed');
});
process.on('SIGINT', function() {
for (var i in clients) {
var socket = clients[i].socket;
socket.end();
}
server.close();
});
server.on('listening', function() {
var addr = server.address();
console.log('Listening Start on Server - ' + addr.address + ':' + addr.port);
});
server.listen(11111, '127.0.0.1');
// vim: set sw=2 sts=2 et :
クライアント側(非常駐プロセス)
こちらもソースコードのみの紹介になります。
var net = require('net');
var options = {};
options.host = process.argv[2];
options.port = process.argv[3];
var client = net.connect(options);
client.on('error', function(e) {
console.error('Connection Failed - ' + options.host + ':' + options.port);
console.error(e.message);
});
client.on('connect', function() {
console.log('Connection - ' + options.host + ':' + options.port);
});
process.on('SIGINT', function() {
console.log('Connction Closed - ' + options.host + ':' + options.port);
client.end();
});
process.stdin.on('data', function(data) {
process.stdout.write('[S] ' + data);
client.write(data);
});
client.on('data', function(chunk) {
process.stdout.write(chunk.toString());
});
client.on('end', function(had_error) {
console.log('Connction End - ' + options.host + ':' + options.port);
});
client.on('close', function() {
console.log('Client Closed');
process.exit(0);
});
試し方
ターミナルが三つ必要になります。
まず、一つ目のターミナルでサーバを起動します。
$ node server.js
次に、二つ目のターミナルでクライアントからサーバに接続します。第2引数にサーバのIPアドレス、第3引数にサーバのポート番号を指定します。
$ node client.js 127.0.0.1 11111
クライアント間でデータを送受信させたいので、もう一つクライアントが必要です。なので、三つ目のターミナルでもクライアントからサーバに接続します。
$ node client.js 127.0.0.1 11111
この段階で一つ目のターミナルを確認すると、二つ目のターミナルのクライアントのポート番号と三つ目のターミナルのクライアントのポート番号を確認できます。
Connection Start(1/3) - 127.0.0.1:49238
Connection Start(2/3) - 127.0.0.1:49239
さて、いよいよです。
一方のクライアントでもう一方のクライアントのポート番号を入力してみましょう。
49239
もう一方のクライアントを確認してみましょう。
[R] test data
クライアント間でデータを送受信できました。
まとめ
呆れた顔が目に浮かびます。いまどきのSocket.IOを使えばチャットを実装できるそうです。そういう技術がそろっている時代に、このような実装に挑戦して意味があるのでしょうか?そういう疑問もあるかもしれませんが、できそうだと思ったら、試してみたくなってしまったのです。
試してみて気付いたことはいくつかあります。一つは、サーバ側にクライアント間の通信用のプロトコルを実装すれば、もう少しマシな通信が実装できそうだということ。もう一つは、複数の機械を制御するためには、プロセス間通信みたいな仕組みが必要そうだということ。ちょっとした気付きでしたが、有意義な経験だったと思います。