Skip to content

Instantly share code, notes, and snippets.

@raggi
Created October 17, 2010 17:42
Show Gist options
  • Save raggi/631056 to your computer and use it in GitHub Desktop.
Save raggi/631056 to your computer and use it in GitHub Desktop.
chat server example using EM::Channel pub-sub, with simple tracing for teaching
require 'eventmachine'
require 'socket'
class Client < EM::Connection
include EM::P::LineText2
HELP = "Server - Welcome to ghettochat. Use /nick to set your nick.\n"
def initialize(global_channel)
@global = global_channel
end
def post_init
@port, @ip = Socket.unpack_sockaddr_in get_peername
@name = "#{@ip}:#{@port}"
@subscription = @global.subscribe(self, :on_global)
global_broadcast "connected"
send_data HELP
end
def unbind
@global.unsubscribe(@subscription)
global_broadcast "disconnected"
end
def receive_line(line)
case line.strip
when /^$/ # empty?
when %r%^/nick (\w+)%
@name = $1
else
global_broadcast line
end
end
# new messages from the channel come in here from the subscription (based on
# the EM::Callback args given to @global.subscribe)
def on_global(message)
send_data(message)
end
def global_broadcast(message)
@global << "#{@name} - #{message}\n"
end
def inspect
"#<#{self.class.name}:#{'0x%x' % object_id} #{@ip}:#{@port}>"
end
end
def WithTracing(klass)
Class.new(klass) do
(instance_methods - Class.instance_methods).each do |m|
eval <<-RUBY
def #{m}(*a)
arglist = a.map {|o| o.inspect }.join(', ')
puts "\#{self.inspect}.#{m}(\#{arglist}\#{', &block' if block_given?})"
super
end
RUBY
end
end
end
TracedClient = WithTracing(Client)
global_channel = EM::Channel.new
EM.run do
trap(:INT) { EM.stop }
EM.start_server('127.0.0.1', 9000, TracedClient, global_channel)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment