FLYING

/* TODO: 気の利いた説明を書く */

一対一チャット

某書籍に載っていたコードを簡略化したもの。cygwin版のRubyではちゃんと動くけど、mswin32版だと $stdin.gets でブロックされて思うように動かないみたい。スレッドとソケットを組み合わせれば色々できそうなんだけど、なかなか思うようにいかないのなー。

うさげ

ruby chat.rb 1234

まず、ポート番号を指定してサーバーを起動する。

ruby chat.rb localhost 1234

次に、ホスト名とポート番号を指定してクライアントを起動する。

発言するときはそのまま送りたい文章を入力。終了したいときは「quit」を送信する。ここら辺の動作はサーバー・クライアント共通になっているので、とても簡単。

ソース

#!/usr/bin/ruby
# chat.rb

require 'socket'
require 'thread'
Thread.abort_on_exception = true

host = ARGV.shift
unless port = ARGV.shift
  host, port = nil, host
  post ||= 0
end

class Chat
  def initialize(sock)
    @sock = sock
  end
  
  def start
    thread = Thread.start { local }
    remote
    thread.exit
  end
  
  def local
    while line = gets do
      line.chop!
      @sock.puts(line)
      break if line =~ /^quit/
    end
  end
  
  def remote
    while line = @sock.gets do
      line.chop!
      puts "> #{line}"
      break if line =~ /^quit/
    end
  end
end

if host then
  sock = TCPSocket.open(host, port)
  puts "connect: #{sock.peeraddr[2]}"
  begin
    chat = Chat.new(sock)
    chat.start
  ensure
    sock.close
  end
else
  s = TCPServer.open(port)
  puts "listen: #{s.addr[1]}"
  loop do
    killme = Thread.start {
      loop { exit if gets =~ /^quit/ }
    }
    sock = s.accept
    puts "accept: #{sock.peeraddr[2]}"
    killme.exit
    begin
      chat = Chat.new(sock)
      chat.start
    ensure
      puts "leave: #{sock.peeraddr[2]}"
      sock.close
    end
  end
end