多人数チャット
まだまだ続くぜ脳内Ruby祭り。今日のアイテムは一対一チャットの発展形。ただし、以下の理由で実用的ではない。
#!/usr/bin/ruby # chats.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 ChatClient def initialize(host, port) @sock = TCPSocket.open(host, port) puts "connect: #{host}" end def start local = Thread.start { local_session } remote = Thread.start { remote_session } while local.alive? && remote.alive? do end local.kill remote.kill end def local_session while line = gets do line.chomp! break if line =~ /^quit/ @sock.puts(line) end end def remote_session while line = @sock.gets do line.chomp! puts(line) end end def shutdown @sock.close end end class ChatServer def initialize(port) @clients = [$stdout] @threads = [] @sock = TCPServer.open(port) puts "listen: #{port}" end def start local = Thread.start { local_session } remote = Thread.start { remote_session } while local.alive? && remote.alive? do end local.kill remote.kill end def local_session while line = gets do line.chomp! break if line =~ /^quit/ send_message(line, $stdout) end end def remote_session while true do tmp = Thread.new(@sock.accept) {|s| add_client(s) while line = s.gets do line.chomp! send_message(line, s) end delete_client(s) } @threads.push(tmp) end end def add_client(client) @clients.push(client) send_message("#{client.peeraddr[2]} is connected.") end def delete_client(client) @clients.delete(client) send_message("#{client.peeraddr[2]} is closed.") end def send_message(mes, from = nil) @clients.each {|ci| ci.puts(">#{mes}") if ci != from } end def shutdown @threads.each {|ti| Thread.kill(ti) } @clients.each {|ci| ci.puts(">server has been shutdown.") ci.close } @sock = nil @clients = [] @threads = [] end end if host then begin chat = ChatClient.new(host, port) chat.start ensure chat.shutdown end else begin chat = ChatServer.new(port) chat.start ensure chat.shutdown end end
そのまま貼るには長すぎるか?