https://docs.ruby-lang.org/ja/latest/class/TCPServer.html のecho serverのサンプルをmrubyで動かしてみました。
経緯
ThreadなしでIOの並列処理やる方法について調べてたところ、selectやpollを使うということを知りました。
mrubyで試そうと思い、まずmruby-socket
のTCPServerがCRubyのTCPServerと同じように使えるのか調べようとしたところ、Rubyリファレンスマニュアルにいきなりやりたいことそのままなサンプルコードが載ってたのでmrubyで動くか試してみました。
mgemの設定
mgemでmruby-ioとmruby-socketを追加します。
conf.gem :mgem => 'mruby-io'
conf.gem :mgem => 'mruby-socket'
ソースコード
mruby-ioを追加してもCRubyのようにKernelにselectが追加されるわけではないので、IO.select
で呼び出しています。
その他、好みでputs
や<<
を使っている以外はリファレンスマニュアルのコードそのままです。
#
# echo_server.rb
# inspired from https://docs.ruby-lang.org/ja/latest/class/TCPServer.html
#
gs = TCPServer.open("127.0.0.1", 12345)
socks = [gs]
addr = gs.addr
addr.shift
puts "server is on #{addr.join(":")}"
loop do
nsock = IO.select(socks)
next if nsock == nil
for s in nsock[0]
if s == gs
socks << s.accept
puts "#{s} is accepted"
else
if s.eof?
puts "#{s} is gone"
socks.delete(s)
else
str = s.gets
puts "#{s}: #{str}"
s.write(str)
end
end
end
end
使ってみる
./path/to/mruby echo_server.rb
で起動後、telnetからアクセスしてみます
$ telnet 127.0.0.1 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
vn9arh9ahv9pfbhp0dzb dzb o
vn9arh9ahv9pfbhp0dzb dzb o
Hello, mruby!
Hello, mruby!
地味ですね。
IO.selectが使えるクラスはどれ?
IO
を継承しているクラスなら使えると思うんですが、mruby-socket
のソースコード追えなかったのでmirbで確かめてみました(というかrubyなら先にそれ試すか普通・・・)
$ ./mruby/bin/mirb
mirb - Embeddable Interactive Ruby Shell
> TCPServer
=> TCPServer
> TCPServer.class
=> Class
> TCPServer.superclass
=> TCPSocket
> TCPSocket.superclass
=> IPSocket
> IPSocket.superclass
=> BasicSocket
> BasicSocket.superclass
=> IO
TCPServer
ばっちりIO
のサブクラスのようです。
その他参考にしたページ
-
8-18 poll()を利用したデータ受信プログラム:Geekなぺーじ
- 最初これを写経しました
-
I/Oを多重化するためのシステムコール(select, poll, epoll, kqueue) - $shibayu36->blog;
- select()とpoll()の違いについてなど