Ping Pong with ruby and EventMachine object protocol
Intro
Recently I needed to pass some simple ruby objects over the network, I found out that the object protocol provided by EventMachine was very well suited for my case.
In this post I want to go through a small example that illustrates how to use the object protocol to communicate between a server and a client. The example is a variant on the theme of network ping pong
Note: all the code used in this post is available as a gist on github, to obtain the code as a local git repository you can just do
git clone git://gist.github.com/309643
Let's start with ball
With no doubt in order to play ping pong we need a ball, here's the code for our Ball class that
The code is pretty simple, our ball is an object that every time is hit produces a sound (alternating between ping and pong), if you want to try to hit a ball yourself just open irb and do the following
require 'ball'
ball = Ball.new
5.times { ball.hit }
you should see the ball "saying" ping/pong and enumerating the number of times it's been hit.
The player
So far nothing was specific to EventMachine, the Ball class is only a plain and simple ruby class.
Since we want to have our server and client to play ping pong using our ball in the same way there's some behaviour we want to share among them, specifically we want them both to hit the ball when they receive it.
We're going to write this shared piece of behaviour in the player module
Let's go through the player module code and see what we defined
- We include the EventMachine object protocol using "include EM::P::ObjectProtocol", this is in order to be able to use the protocol in our server and client.
- We define the receive_object method, this method will be called by EventMachine every time our server or client receives an object, the received object is passed as argument, in this case we alway expects to receive a ball object then we hit it and we send it back on the other end of the network connection.
- We define the unbind method, unbind will be invoked by EventMachine every time the current connection is closed.
The client
At this point writing our client script it's very little effort
The code for the client is really straightforward, we start the event machine reactor with EM.run and within the reactor loop e start a connection to the localhost and port 9797, we also pass to the connection our Player module so the connection get mixed in all the methods defined in the module and is ready to play ping pong properly.
The server
The server code is similar to the client one with few changes, let's take a look:
We define a new module ServerPlayer which include the original Player module and defines a the method post_init, this method is called on the server process by EventMachine every time a client establishes a connection with the server.
In our case post_init is used to serve the ball the client in order to get the ping pong game started
Time to play
Code wise we're done, what we need to do now is to start the actual game, all what we need are two shell open in the directory where our source files are.
From the first console we start the server with the command
ruby server_player.rb
and from the second shell we start the client with the command
ruby client_player.rb
We should see the on the two consoles the output of client and server happily playing ping pong and counting the number of hits.
The ball object travels across the network connection from the server to the client and back every time is hit, producing the right sound for the hit number.
It's obviously possible to start multiple client_player and having the server playing many simultaneus matches.
That's all
I hope this post will help someone getting started with the EventMachine object protocol, any comment, or code contribution is really welcome.
Comments [0]