I just discovered EventMachine. EM is, at its least, an event-driven library around which you can build a custom TCP server. The nitty-gritty of listening, sending and receiving, and multiplexing connections is all done for you.
That's selling it short, though, because EventMachine can do a lot more. In its own words, EventMachine "provides event-driven I/O using the Reactor pattern." It can be used for other client/server models like serial ports or even interactive keyboard I/O. But it really stands out for abstracting away the low-level hassles of writing a TCP daemon.
Here's a simple Echo service built using EventMachine. (Borrowed from the README file)
require 'rubygems'
require 'eventmachine'
module EchoServer
def receive_data data
send_data ">>>you sent: #{data}"
close_connection if data =~ /quit/i
end
end
EventMachine::run {
EventMachine::start_server "192.168.0.100", 8081, EchoServer
}
Here's an example I made. You can pass a class to EventMachine::start_server, and each new connection will create a new instance of your class. That allows you to use instance variables to record distinct state for each connection. This example buffers up the client input until the client sends a ".<CRLF>" a la SMTP, or a maximum of 10 lines.
require 'rubygems'
require 'eventmachine'
class DataBuffer < EM::Protocols::LineAndTextProtocol
def initialize
puts "init'ing new instance of #{self.class.to_s}"
@line_ctr = 0
@databuf = []
end
def receive_data(data)
@databuf << data
@line_ctr += 1
if data == ".\r\n" || @line_ctr == 10
if data == ".\r\n"
@databuf.pop
end
send_data(@databuf.to_s)
reset_databuf()
end
end
private
def reset_databuf
@line_ctr = 0
@databuf = []
end
end
EventMachine::run {
EventMachine::start_server "127.0.0.1", 8081, DataBuffer
}
And the best part is, I've only been playing with EventMachine for about an hour! I've only begun to understand what it can do.So, yeah. EventMachine is badass. You should check it out.
No comments:
Post a Comment