Ruby GServer を叩いてみる

GServer自体は簡単で良い物なんだけど、多少気になる挙動があるのでメモ。

  • echos.rb
#!/usr/bin/env ruby

require 'gserver'

class EchoServer < GServer
  def self.start
    s = self.new(10001, '0.0.0.0', 1000)
    trap(:INT) { s.stop }
    s.start
    s
  end

  def initialize(port, *args)
    super(port, *args)
  end

  def serve(io)
    r = io.gets.strip
    io.puts "[#{r}] #{Time.now}"
  end
end

STDERR.sync = STDOUT.sync = true
server = EchoServer.start

until server.stopped?
  sleep 1
end
  • client.rb
#!/usr/bin/env ruby

require 'socket'

STDOUT.sync = STDERR.sync = true

20.times {
  Thread.new {
    while true
      s = TCPSocket.new(ARGV[0], 10001)
      s.puts Thread.current.inspect
      puts s.gets
      s.close
    end
  }
}
sleep 100000

本体はもちろん

  def serve(io)
    r = io.gets.strip
    io.puts "[#{r}] #{Time.now}"
  end

ですが、ここを

  def serve(io)
    r = io.gets.strip
    io.puts "[#{r}] #{Time.now}"
    while io.gets; sleep 1; end  # 読み捨てる
  end

と「nilを返すまでio.getsで捨てる」と書くと、数回〜数万回アクセスを受けた後にハングアップするという現象。

もっとも「io.gets == nil まで読み込む」という処理が適切なのかは不明ですが。