# Packet 0.1.3 - Library for Event Driven Network Programming

**URL:** <https://www.ruby-forum.com/t/packet-0-1-3-library-for-event-driven-network-programming/128808>\
**Category:** Ruby\
**Created:** [February 11, 2008, 6:18pm UTC](https://www.ruby-forum.com/t/packet-0-1-3-library-for-event-driven-network-programming/128808 "2008-02-11T18:18:17Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![gnufied](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/ea666f/32.png) [@gnufied](https://www.ruby-forum.com/u/gnufied)\
**Post date:** [February 11, 2008, 6:18pm UTC](https://www.ruby-forum.com/t/packet-0-1-3-library-for-event-driven-network-programming/128808/1 "2008-02-11T18:18:17Z")

</div>

Hi Folks,

I am pleased to announce new release of “Packet”, A pure ruby library  
for Event  
Driven Network Programming.

Packet is a pure ruby library for writing network applications in Ruby.  
It follows Evented Model of network programming and implements almost  
all the  
features provided by EventMachine.

It also provides real easy to use UNIX workers for concurrent  
programming. Interfacing with workers running in separate process is  
one of key differentiators for Packet.

== Changelogs

- Fixed some known bugs while writing data to the socket.
- Improved code structure and layout.
- Some other fixes for Mac OSX and UNIX Sockets.

== Examples  
=== A Simple Echo Server:  
require “rubygems”  
require “packet”

class Foo  
def receive\_data p\_data  
send\_data(p\_data)  
end

def post\_init  
puts “Client connected”  
end

def connection\_completed  
puts “Whoa man”  
end

def unbind  
puts “Client Disconnected”  
end  
end

Packet::Reactor.run do |t\_reactor|  
t\_reactor.start\_server(“localhost”,11006,Foo)  
end

Those new to network programming with events and callbacks, will note  
that,  
each time a new client connects an instance of class Foo is  
instantiated.  
When client writes some data to the socket, receive\_data method is  
invoked.

Although Packet implements an API similar to EventMachine, but it  
differs  
slightly because of the fact that, for a packet app, there can be more  
than one  
reactor loop running and hence, we don’t use Packet.start\_server(…).

=== A Simple Http Client  
class WikiHandler  
def receive\_data p\_data  
p p\_data  
end

def post\_init  
end

def unbind  
end

def connection\_completed  
send\_data(“GET / \r\n”)  
end  
end

Packet::Reactor.run do |t\_reactor|  
t\_reactor.connect(“[en.wikipedia.org](http://en.wikipedia.org)”,80,WikiHandler)  
end

=== Using Callbacks and Deferables  
See the code

=== Using Workers  
Packet enables you to write simple workers, which will run in  
different process and gives you nice  
evented handle for concurrent execution of various tasks.

When, you are writing a scalable networking application  
using Event Model of network programming,  
sometimes when processing of certain events take time,  
your event loop is stuck there. With green  
threads, you don’t really have a way of paralleling  
your request processing. Packet library, allows  
you to write simple workers, for executing long  
running tasks. You can pass data and callbacks as an  
argument.

When you are going to use workers in  
your application, you need to define  
constant WORKER\_ROOT,  
which is the directory location, where  
your workers are located. All the workers defined in that directory  
will be automatically, picked and forked in a  
new process when your packet app starts. So, a typical  
packet\_app, that wants to use workers, will look like this:

packet\_app\_root  
|  
|\_\_ lib  
|  
|\_\_\_ worker  
|  
|\_\_\_ config  
|  
|\_\_\_ log

You would define WORKER\_ROOT = PACKET\_APP\_ROOT/worker

All the workers must inherit class Packet::Worker, and hence a  
general skeleton of worker will look like:

class FooWorker \< Packet::Worker  
set\_worker\_name :foo\_worker #=\> This is necessary.  
def receive\_data p\_data  
end

```
 def connection_completed
 end

 def unbind
 end

 def post_init
 end

```

end

All the forked workers are connected to master via  
UNIX sockets, and hence messages passed to workers from master  
will be available in receive\_data method. Also,  
when you are passing messages to workers, or worker is passing  
message to master ( in a nutshell, all the internal  
communication between workers and master ) directly takes  
place using ruby objects. All the passed ruby objects are  
dumped and marshalled across unix sockets in a non blocking  
manner. BinParser class parses dumped binary objects and  
makes sure, packets received at other end are complete.  
Usually, you wouldn’t need to worry about this little detail.

Packet provides various ways of interacting with  
workers. Usually, when a worker is instantiated, a proxy for  
that worker will also be instantiated at master  
process. Packet automatically provides a worker proxy(See meta\_pimp.rb)  
for you, but if you need to multiplex/demultiplex  
requests based on certain criteria, you may as well define your  
own worker proxies. Code, would like something like this:

class FooWorker \< Packet::Worker  
set\_worker\_proxy :foo\_handler  
end

When you define, :foo\_handler as a proxy for  
this worker, packet is gonna search for FooHandler class and  
instantiate it when the worker gets started. All  
the worker proxies must inherit from Packet::Pimp.  
Have a look at, Packet::MetaPimp,  
which acts as a meta pimp for all the workers,  
which don’t have a explicit worker proxy defined.

=== A complete Case :

Just for kicks, lets write a sample server,  
which evals whatever clients send to it. But, assuming this ‘eval’ of  
client data can be potentially time/cpu  
consuming ( not to mention dangerous too ), we are gonna ask our  
eval\_worker, to  
perform eval and return the result to master process, which in  
turn returns the result to happy client.

# APP\_ROOT/bin/eval\_server.rb

EVAL\_APP\_ROOT = File.expand\_path(File.join(File.dirname( **FILE** ) +  
“/…”))  
[“bin”,“worker”,“lib”].each { |x| $LOAD\_PATH.unshift(EVAL\_APP\_ROOT

- “/#{x}”)}  
WORKER\_ROOT = EVAL\_APP\_ROOT + “/worker”

eval\_server in  
# your master, for each connected client, but worker\_receive  
will be always  
# be invoked for the instance, which originally made the request.  
# If you need fine control, over this behaviour, you can  
implement a worker proxy  
# on the lines of meta\_pimp class. This API will change in  
future perhaps, as i  
# expect, better ideas to come.  
def worker\_receive p\_data  
send\_data “#{p\_data[:data]}\n”  
end

```
 def show_result p_data
   send_data("#{p_data[:response]}\n")
 end

 def connection_completed
 end

 def post_init
 end

 def wow
   puts "Wow"
 end

```

end

Packet::Reactor.run do |t\_reactor|  
t\_reactor.start\_server(“localhost”, 11006,EvalServer) do |instance|  
instance.wow  
end  
end

# APP\_ROOT/worker/eval\_worker.rb

```
class EvalWorker < Packet::Worker
set_worker_name :eval_worker
def worker_init
  p "Starting no proxy worker"
end

def receive_data data_obj
  eval_data = eval(data_obj[:data])
  data_obj[:data] = eval_data
  data_obj[:type] = :response
  send_data(data_obj)
end

```

end

=== Disable auto loading of certain workers:  
Sometimes, you would need to start a  
worker at runtime and don’t want this pre-forking mechanism.  
Packet, allows this. You just need to define  
“set\_no\_auto\_load true” in your worker class and worker  
will not be automatically forked. Although name is a bit misleading  
perhaps.

Now, at runtime, you can call start\_worker(:foo\_worker, options)  
to start a worker as usual. It should  
be noted that, forking a worker, which is already  
forked can be disastrous, since worker names are being  
used as unique keys that represent a worker.

=== Real World Applications  
Packet is being used in our internal applications. Packet also forms  
core of new version of BackgrounDRb.

== Performance:  
With 500 clients each posting 10000 echo requests  
with Packet:

real 25m15.002s  
user 21m37.621s  
sys 2m49.967s

with EM

real 25m6.502s  
user 21m46.370s  
sys 2m48.983s

Since EM uses Epoll, performance of EventMachine will be much better  
for larger set of file descriptors.  
If your sole criteria is performance go with EventMachine. Also, EM  
implements secure tcp and udb, while packet has  
no support for these protocols. It may come in future.

== Code:  
SVN Code for packet is on google code, svn repo is:  
[http://packet.googlecode.com/svn/trunk/](http://packet.googlecode.com/svn/trunk/)

Rubyforge URL:  
[http://rubyforge.org/projects/packet/](http://rubyforge.org/projects/packet/)

== Credits  
Francis for awesome EventMachine lib, which has constantly acted as  
an inspiration.  
Ezra, for being a early user and porting mongrel to run on top of  
packet.

–  
Let them talk of their oriental summer climes of everlasting  
conservatories; give me the privilege of making my own summer with my  
own coals.

[http://gnufied.org](http://gnufied.org)

> **[Homepage - Market Simplified](https://marketsimplified.com/)**
>
> An exclusive financial services co-creative studio delighting banks, brokers and NBFCs with the last mile digital transformations.
