So,
EventMachine is a fast and easy framework for networking in
Ruby .
EventMachine uses an event-oriented (asynchronous) mechanism for handling network connections. (The differences between synchronous and asynchronous models of processing network connections are covered in a lot of information on the network).
Since, in the Russian-language Internet is very scarce information on this wonderful gem'u spread this article.
Setting a standard enough for a Ruby programmer:
gem install eventmachineLet's start with an example from the documentation (somewhat modified):
require 'rubygems' require 'eventmachine' class EchoServer < EventMachine::Connection def post_init puts " " end def receive_data data send_data ">>>
')
Now we will analyze in order (the reverse - it will be more convenient):
EventMachine :: run - initializes and starts the message processing loop (
EventReactor ), it returns from this function only when the
stop_event_loop method is
called . The method can (and should) be passed a block that runs before the start of the message processing cycle. For example, we can initialize a server here, configure timers, establish a client connection, etc. In this example, we start the echo server, for this is the method (module method
EventMachine )
EventMachine :: start_server , its parameters are the IP address and port for listening, in our example the IP is empty so that you can connect from any host. The next and probably most important parameter is the connection handler — for example, the name of a class (a
subclass of EventMachine :: Connection ) or a module (in this case, the module is mixed into an anonymous subclass of
EventMachine :: Connection ). In this example, this is the
EchoServer class.
For each connection to the server, an object of the EchoServer class is initiated !!!In the message processing loop (
EventReactor ), messages are initiated — in this context, these are calls to the methods of an object of the
EchoServer class. The main messages are:
- post_init - called after connection setup
- unbind - called when connection is broken
- receive_data - called when a message is received from the connection
In the above example, after the connection with the client is established, the message “Connection to the server” is displayed, if the connection is closed, the connection is closed. When a message is received, it is sent back using the
send_data method (to send a message); if a quit message is received, the connection is closed.
For more information about class methods, see the documentation.
Everything is almost the same with a client - examples can be found on the Internet, including in Russian.
In general, the easiest way is to test using telnet:
telnet localhost 11777We will consider more interesting topics.
I already met on Habré a chat made using
EventMachine , however all its goodies were not used there. Now we will write a simple chat (I will not lie, but I think that it will withstand 1000 connections, if you correct the code a little, as a hint - the
EventMachine.defer method).
Consider the channels
EventMachine :: Channel . This mechanism is not new at all and is used in various systems; moreover, it is a whole pattern. The mechanism is the following: there is a channel (well, let's say a long corridor of the floor of an office building), and there are subscribers (those who opened the doors to hear everything that happens in the corridor). Anyone, not even a subscriber (the one who did not open the door) can send a message to the channel (shout anything into the corridor) and all subscribers will receive (hear) it. You can unsubscribe from the channel (close the door).
So, the channel has three methods:
subscribe (subscribe),
push (send message),
unsubscribe (unsubscribe). Below is the implementation of the chat (with one channel - room)
require 'rubygems' require 'eventmachine' require 'socket' class User < EventMachine::Connection @@room = EventMachine::Channel.new attr_reader :port, :ip, :sid def receive_data data @@room.push("
In general, programming with
EventMachine is somewhat more complicated than usual. This is due to asynchrony, the use of a large number of blocks, procedures and other things. In the examples above, this is almost
invisible , but if you want to use
EventMachine you will have to face it.