node.jsを動かしてみる

さてさて、みんな大好きJavaScript
サーバ側でもJavaScript


ということでさっそくnode.jsの動作確認編に参ります。


http://nodejs.org/ にサンプルが載っているので、さっそくこれを動かしてみます。

まずは httpサーバ。

// sample_http.js
var sys = require('sys'),
   http = require('http');
http.createServer(function (req, res) {
  setTimeout(function () {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
  }, 2000);
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');
$ node sample_http.js

別の端末を開いて確認します。

$ curl http://127.0.0.1:8000
Hello World

おおお、すばらしい!


では引き続きtcpサーバの方も試してみます。

// sample_tcp.js
var tcp = require('tcp');
var server = tcp.createServer(function (socket) {
  socket.setEncoding("utf8");
  socket.addListener("connect", function () {
    socket.write("hello\r\n");
  });
  socket.addListener("data", function (data) {
    socket.write(data);
  });
  socket.addListener("end", function () {
    socket.write("goodbye\r\n");
    socket.end();
  });
});
server.listen(7000, "localhost");
$ node sample_tcp.js
The 'tcp' module is now called 'net'. Otherwise it should have a similar intarface.


ふむふむ、ではtcpをnetに書き換えてみます。

// sample_tcp.js
var net = require('net');
var server = net.createServer(function (socket) {
  socket.setEncoding("utf8");
  socket.addListener("connect", function () {
    socket.write("hello\r\n");
  });
  socket.addListener("data", function (data) {
    socket.write(data);
  });
  socket.addListener("end", function () {
    socket.write("goodbye\r\n");
    socket.end();
  });
});
server.listen(7000, "localhost");
$ node sample_tcp.js
$ curl http://127.0.0.1.:7000/

おおお?レスポンスがまったく返ってきません。
Ctrl+Cで止めてやると以下のようなレスポンスが返ってきてました。

hello
GET / HTTP/1.1
User-Agent: curl/7.19.7 (i486-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
Host: 127.0.0.1.:7000
Accept: */*

うーん、'goodbye'がレスポンスに含まれていません。
ちょこちょこっといじってみたのですが、endイベントが呼ばれていないことが原因でした。

また、APIDocumentに載っているサンプルによると、tcp#createServerメソッドに渡した関数にわたる引数は、socketオブジェクトからstreamオブジェクトに変更されている模様。


なので、ちょいと修正したものを。

// sample_tcp.js
var tcp = require('tcp');
var server = tcp.createServer(function (stream) {
  stream.setEncoding("utf8");
  stream.addListener("connect", function () {
    stream.write("hello\r\n");
  });
  stream.addListener("data", function (data) {
    stream.write(data);
    // 以下、追加行
    stream.write("goodbye\r\n");
    stream.end();
  });
  stream.addListener("end", function () {
    // stream.write("goodbye\r\n"); endした後なのでwriteできない
    // stream.end();
  });
});
server.listen(7000, "localhost");

dataイベントの中でstream#endメソッドを呼んでやると正常にレスポンスを返すようになりました。

$ curl http://127.0.0.1.:7000/
hello
GET / HTTP/1.1
User-Agent: curl/7.19.7 (i486-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
Host: 127.0.0.1.:7000
Accept: */*
goodbye

おお、すばらしい!


でもtcpモジュールとnetモジュールのAPIの互換性って大丈夫なんでしょうか??
既存のフレームワークがちゃんと動くか結構心配になってきました。


せっかくなので、次回は Express を試してみようと思います。