echoサーバーを書こう
2010-12-10
こんにちは、@lopnorこと檀上です。と、これまで誰も名乗らずにここまできてしまいましたJPerl Advent Calendar 2010 - perl6 trackですが、ここでこれまでの執筆者をご紹介します。
- @risouさん
- [/articles/advent-calendar/2010/perl6/7:title=インタラクティブな実行環境を使おう]
- @uasiさん
- [/articles/advent-calendar/2010/perl6/8:title=モジュールを公開してみよう]
- @VienosNotesさん
- [/articles/advent-calendar/2010/perl6/9:title=『Perl6入門』入門]
- @lopnor
- 残りの記事
です。まだまだ原稿が足りないので、Perl 6について語っちゃうよ!という方はぜひお声がけください。よろしくお願いします!
echoサーバーを書こう
さて、今日はネットワークプログラミングに挑戦です。先日twitterのタイムラインを読んでくるスクリプトがありましたが、やっぱり今時ネットワーク経由でデータをやり取りしてナンボ、というところがあります。前回はクライアントでしたが、今回はサーバーをつくってみようと思います。というとまずはechoサーバーを書かないといけないですね。
echoサーバーの動作イメージはこんな感じです。
$ perl6 echo_server.pl 5000 & [1] 4980 $ telnet 127.0.0.1 5000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hoge hoge fuga fuga ^] telnet> quit Connection closed.
echo_server.plはこんな感じ。
#!/usr/bin/env perl6 use v6; # constants sub PF_INET {2} sub SOCK_STREAM {1} sub TCP {6} sub MAIN ($port = '5000', :$host = '0.0.0.0') { my $server = IO::Socket::INET.socket( PF_INET, SOCK_STREAM, TCP ); $server.bind($host, $port); $server.listen; while my $conn = $server.accept { while my $str = $conn.recv { $conn.send($str); } $conn.close; } $server.close; } # vim: ft=perl6 :
と、何の変哲もないコードでした。これで僕の環境ではちゃんと動きます。で、これ実はほとんどrakudo/t/spec/S32-io/IO-Socket-INET.plからパクったものなんですが、これがspectest.dataからコメントアウトされており、いくつかの環境で正しく動作しない模様です。はやくなおるといいですね。
ベンチマーク
さて、このサーバーとperl5で書いたサーバーを比較してみました。
#!perl use strict; use warnings; use IO::Socket; my $server = IO::Socket::INET->new( LocalPort => 5000, Listen => SOMAXCONN, Reuse => 1, ); while (my $conn = $server->accept) { while ($conn->sysread(my $str, 1024)) { $conn->syswrite($str); } $conn->close; } $server->close; # from http://d.hatena.ne.jp/naoya/20070311/1173629378
こんなの。これを、別のマシンから
$ time (for i in `seq 1 1000`; do echo $i | nc 10.0.87.6 5000 > /dev/null;done)
としてみました。
# perl6 $ time (for i in `seq 1 1000`; do echo $i | nc 10.0.87.6 5000 > /dev/null;done) (; for i in `seq 1 1000`; do; echo $i | nc 10.0.87.6 5000 > /dev/null; done; ) 0.68s user 2.78s system 19% cpu 17.548 total # perl5 $ time (for i in `seq 1 1000`; do echo $i | nc 10.0.87.6 5000 > /dev/null;done) (; for i in `seq 1 1000`; do; echo $i | nc 10.0.87.6 5000 > /dev/null; done; ) 0.68s user 2.80s system 20% cpu 16.667 total
大差ないですね。つないでやり取りして切る、だけであればそれほど差はないようです。このあと、httpサーバーを書くなどした場合、文字列処理で差が出てくるのだと思います。