ザキンコのブログ

ザキンコの日記のはてなブログ版です。

WindowsのRubyでTCPServerを使うときメモ

例えばこういうコードをコマンドプロンプト(cmd)から実行すると、server.acceptでブロックした後、CTRL-Cを受け付けなくなってウインドウを閉じるかrubyプロセスをkillするしかないみたい。Windows版の仕様かな。環境はWindows 7(64bit)、ruby 1.9.3p194 (2012-04-20) [i386-mingw32]で確認。
server.acceptも子スレッドから呼び出すようにして、メインスレッドは子スレッドが終了するまでjoinで待つようにしたら大丈夫っぽい。
(2013.4.4追記)
ruby 2.0.0p0 (2013-02-24) [i386-mingw32]では、server.acceptでブロックした後、CTRL-Cを受け付けるようになっていて、無事にスクリプトを停止できました。

require "socket"
server = TCPServer.new(21)
loop do
  client = server.accept
  
  Thread.new(client) do |cl|
    begin
      loop { cl.puts eval cl.gets }
    rescue
    ensure
      cl.close
    end
  end
end

こんな感じ。

require "socket"
server = TCPServer.new(21)

Thread.new(server) do |s|
  loop do
    client = s.accept
    
    Thread.new(client) do |cl|
      begin
        loop { cl.puts eval cl.gets }
      rescue
      ensure
        cl.close
      end
    end
  end
end

(ThreadGroup::Default.list - [Thread.current]).each {|th| th.join}
puts "all threads finished"

あと、デフォルトだと子スレッドでエラーが起きても通知されないから

Thread.abort_on_exception = true

も忘れないように。これで通知されます。