海未「今回と次回でネットワークの話をします。HTTPについては少しだけ見ましたが、今回は低レイヤのTCP/UDP通信について見てみましょう」
海未「TCP通信にはnet
モジュール、UDP通信にはdgram
モジュールを使います。まずはTCPからいきますね」
穂乃果「ネットワークの予習はしてきたよっ!」
海未「よい心がけです。では、TCPサーバ、TCPクライアントの順に実装していきましょう」
TCP
海未「最も原始的なサーバはこのようになるでしょう」
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var net = require("net"); var server = net.createServer(); server.on("listening", function() { console.log("listening..."); }); server.on("connection", function(socket) { console.log("connected"); }); server.listen(25252, "127.0.0.1"); |
海未「createServer
が返すnet.Server
のインスタンスはEventEmitter
ですから、on
でリスナーを追加していくことができます」
ことり「listening
とかconnection
とかはネットワーク独自のイベント?」
海未「はい。listening
はTCPサーバが接続を受け付けられるようになったとき、connection
はクライアントから接続されたときに発火します」
ことり「じゃあ、connection
のリスナーで通信すればいいんだね」
海未「これに接続するTCPクライアントはこのようになります」
1 2 3 4 5 6 7 8 9 10 |
var net = require("net"); var socket = new net.Socket(); socket.on("connect", function() { console.log("connected."); socket.end(); }); socket.connect(25252, "127.0.0.1"); |
海未「さきほどのサーバを起動して、別のコンソールからクライアントを実行してみてください」
穂乃果「あ、両方にconnectedって出た」
海未「これで接続はできたことになります。例によってこのScoket
もEventEmitter
です」
海未「では今度は、クライアントからサーバにデータを送ってみましょう」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var net = require("net"); var server = net.createServer(); server.on("listening", function() { console.log("listening..."); }); var data = ""; server.on("connection", function(socket) { socket.on("data", function(chunk) { data += chunk.toString(); }); }); server.on("connection", function(socket) { socket.on("end", function(socket) { console.log(data); }) }) server.listen(25252, "127.0.0.1"); |
1 2 3 4 5 6 7 8 9 10 11 |
var net = require("net"); var socket = new net.Socket(); socket.on("connect", function() { console.log("connected."); socket.write("ファイトだよっ!"); socket.end(); }); socket.connect(25252, "127.0.0.1"); |
海未「さきほどと同じように実行してみてください」
穂乃果「ファイトだよっ!」
海未「そうですね。これでサーバに対してデータが送信できているのが分かると思います」
海未「今度はサーバからクライアントにデータを送信してみましょう。基本的には同じことです」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var net = require("net"); var server = net.createServer(); server.on("listening", function() { console.log("listening..."); }); server.on("connection", function(socket) { socket.write("ちゅんちゅん"); socket.end(); }); server.listen(25252, "127.0.0.1"); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var net = require("net"); var socket = new net.Socket(); socket.on("connect", function() { console.log("connected."); }); var data = ""; socket.on("data", function(chunk) { data += chunk.toString(); }); socket.on("end", function(had_err) { console.log(data); }); socket.connect(25252, "127.0.0.1"); |
ことり「ちゅんちゅん」
海未「いずれも、write
でソケットに書き込み、data
イベントで受信します。data
やend
は見覚えがあるのではないですか?」
穂乃果「ストリームだねっ!」
海未「そうです。ですから、data
ではデータは細切れになりますから、このように変数に貯めていく形の実装にしています」
海未「このサンプルコードは通信部分の説明用ですから、実際に複数のクライアントから同時に接続を受けた場合などは考慮していません。データが混ざらないような工夫が必要でしょう」
UDP
海未「今度はUDP接続です。こちらはdgram
モジュールを使いますが、基本的な考え方は大きくは変わりません」
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var dgram = require("dgram"); var socket = dgram.createSocket("udp4"); socket.on("listening", function() { console.log("listening..."); }); socket.on("message", function(msg, rinfo) { console.log(msg.toString()); }); socket.bind(25252, "127.0.0.1"); |
1 2 3 4 5 6 7 8 |
var dgram = require("dgram"); var socket = dgram.createSocket("udp4"); var buffer = new Buffer("ラブアローシュート!"); socket.send(buffer, 0, buffer.length, 25252, "127.0.0.1", function() { socket.close(); }); |
海未「クライアント、サーバともにソケットを開いて通信をします。サーバ側では、bind
を使うと待ち受けが始まります」
穂乃果「listening
はTCPと同じだね」
海未「はい。message
も、TCPのdata
と似たようなものです」
ことり「えーっと、送る側は・・・」
海未「Buffer
というのを使っていますが、これはデータをバイナリで扱うためのものです。文字列そのままは送れないということですね」
ことり「でも、toString()
で戻すだけだから簡単だよね」
海未「はい。そしてあとはsend
で送るだけです。TCPよりシンプルだと思います」
海未「低レイヤの通信についてはこんなところです。いよいよ次回はWebアプリの基本、HTTP通信について見ていきましょう」
穂乃果「テンション上がるにゃ~っ!」
ことり「穂乃果ちゃん、それ違うよ・・・」