Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
celluloid chat server
require "socket"
require "rubygems"
require "bundler/setup"
require "celluloid"
module Chat
class ConnectionListener
include Celluloid
def initialize(server, tcp_server)
@server, @tcp_server = server, tcp_server
end
def start
loop do
connection = @tcp_server.accept
@server.async.add_client(connection)
end
end
end
class Server
include Celluloid
trap_exit :client_disconnect
def initialize(port)
@port = port
@clients = []
end
def add_client(connection)
client = Client.new_link(Actor.current, connection)
@clients << client
client.async.start
end
def broadcast(sender, message)
other_clients = @clients.reject { |client| client == sender }
other_clients.each { |client| client.async.tell(message) }
end
def client_disconnect(actor, reason=nil)
@clients.reject! { |client| client == actor }
end
def start
server = TCPServer.new(@port)
ConnectionListener.new(Actor.current, server).async.start
end
end
class MessageListener
include Celluloid
def initialize(client, connection)
@client, @connection = client, connection
@running = true
end
def start
while @running
if @connection.eof?
@running = false
@client.async.exit
terminate
else
message = @connection.gets("\n")
@client.async.message_received(message) if message
end
end
end
end
class Client
include Celluloid
def initialize(server, connection)
@server, @connection = server, connection
end
def exit
@server.async.client_disconnect(Actor.current)
terminate
end
def message_received(message)
@server.async.broadcast(Actor.current, message)
end
def start
MessageListener.new_link(Actor.current, @connection).async.start
end
def tell(message)
@connection.puts(message)
end
end
end
server = Chat::Server.new(3000)
server.async.start
sleep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment