You want applications to be able to talk to each other ... without writing code that (should) scare you.
The Spread Toolkit is, to quote its homepage, an open source toolkit that provides a high performance messaging service that is resilient to faults across local and wide area networks
Now, that description is perhaps not buzzword, rad fuelled 'boom' sockets on steroids, but Spread has been around for a while, and Ubuntu and Debian comes with packages out of the box. Things I like.
Spread also has bindings for a host of languages, including C, Perl, Ruby and Python. So, as an alternative to 0mq, rabbitmq, etc, possibly requiring less commitment, it may be worth a look.
I'll go through running the daemon on Ubuntu, and a Perl script. It is dead simple, though the Perl Module documentation may obscure that a bit.
Install the Spread daemon
As root (or using sudo)
apt-get install spread libspread-perl
At least in Ubuntu 10.04 LTS, there is a problem with the package at the time of writing where the maintainer has specified the configuration file location incorrectly. Also, since the config file binds to localhost, you need to set the process name with the -n switch for it to run. If not it quits with an error message similar to:
[Tue 17 Aug 2010 14:59:41] Conf_init: My proc id (127.0.1.1) is not in configuration Exit caused by Alarm(EXIT)
There is a Ubuntu bug report, but here is a quick
rundown on how to fix this:
- update /etc/init.d/spread
change the line:
DOPTIONS="-c /etc/spread.conf"
to
DOPTIONS="-c /etc/spread/spread.conf"
- update the /etc/default/spread file to:
# Change to enable spread ENABLED=1 # Options, see spread.1 for list OPTIONS="-n localhost"
/etc/init.d/spread start
Spread on Perl
The simplest demo I could create was as follows:1 #!/usr/bin/perl 2 3 use strict; 4 use warnings; 5 6 use Spread; 7 8 # connect 9 my ( $mbox, $private_group ) = Spread::connect( { 10 spread_name => '4803@localhost', 11 private_name => 'myname', 12 group_membership => 0 # we don't want to hear who joins/leaves groups 13 }); 14 die 'Unable to connect' unless (defined($mbox)); 15 16 # join a group 17 Spread::join($mbox, 'mygroup') or die 'Failed to join group'; 18 19 # multicast message to group 20 Spread::multicast( $mbox, AGREED_MESS, 'mygroup', 0, "this is your message" ); 21 22 # poll for messages 23 my ($messsize); 24 while ($messsize = Spread::poll($mbox)) { 25 print "--Next message: $messsize bytes\n"; 26 my ( $service_type, $sender, $groups, $mess_type, $endian, $message ) = Spread::receive($mbox); 27 print "\tsender : $sender\n"; 28 print "\tgroups : " . join(',', @$groups) . "\n"; 29 print "\tmessage : [$message]\n"; 30 } 31 32 Spread::disconnect($mbox);This should give you the following output:
--Next message: 100 bytes sender : #myname#localhost groups : mygroup message : [this is your message]If you want to also have a look at the Message join/leave/etc messages, here's the same example slightly modified:
1 #!/usr/bin/perl 2 3 use strict; 4 use warnings; 5 use Data::Dumper; 6 use Spread qw(:MESS); 7 8 my %types = ( 9 0x00000001 => 'UNRELIABLE_MESS', 10 0x00000002 => 'RELIABLE_MESS', 11 0x00000004 => 'FIFO_MESS', 12 0x00000008 => 'CAUSAL_MESS', 13 0x00000010 => 'AGREED_MESS', 14 0x00000020 => 'SAFE_MESS', 15 0x0000003f => 'REGULAR_MESS', 16 0x00000040 => 'SELF_DISCARD', 17 0x00000100 => 'CAUSED_BY_JOIN', 18 0x00000200 => 'CAUSED_BY_LEAVE', 19 0x00000400 => 'CAUSED_BY_DISCONNECT', 20 0x00000800 => 'CAUSED_BY_NETWORK', 21 0x00001000 => 'REG_MEMB_MESS', 22 0x00002000 => 'TRANSITION_MESS', 23 0x00003f00 => 'MEMBERSHIP_MESS', 24 0x003fc000 => 'RESERVED', 25 0x00400000 => 'REJECT_MESS', 26 0x01000000 => 'DROP_RECV', 27 0x80000080 => 'ENDIAN_RESERVED', 28 ); 29 30 # connect 31 my ( $mbox, $private_group ) = Spread::connect( { 32 spread_name => '4803@localhost', 33 private_name => 'myname', 34 group_membership => 1 35 }); 36 die 'Unable to connect' unless (defined($mbox)); 37 38 # join a group 39 Spread::join($mbox, 'mygroup') or die 'Failed to join group'; 40 41 # multicast to group 42 Spread::multicast( $mbox, AGREED_MESS, 'mygroup', 0, "this is your message" ); 43 44 # Poll mailbox 45 my ($messsize); 46 while ($messsize = Spread::poll($mbox)) { 47 print "--Next message: $messsize bytes\n"; 48 my ( $service_type, $sender, $groups, $mess_type, $endian, $message ) = Spread::receive($mbox); 49 print "\tservice_type: $service_type (" . 50 join('|', map { $types{$_} } grep { $_ & $service_type } ( keys %types ) ) . 51 ")\n"; 52 print "\tsender : $sender\n"; 53 print "\tgroups : " . Dumper($groups); 54 print "\tmess_type : $mess_type\n"; 55 print "\tendian : $endian\n"; 56 $message =~ s/[^[:print:]]/./g; 57 print "\tmessage : [$message]\n"; 58 } 59 60 Spread::disconnect($mbox);Which outputs
--Next message: 228 bytes service_type: 4352 (MEMBERSHIP_MESS|REG_MEMB_MESS|CAUSED_BY_JOIN) sender : mygroup groups : $VAR1 = [ '#myname#localhost' ]; mess_type : 0 endian : message : [......jL........#myname#localhost...............] --Next message: 100 bytes service_type: 16 (REGULAR_MESS|AGREED_MESS) sender : #myname#localhost groups : $VAR1 = [ 'mygroup' ]; mess_type : 0 endian : message : [this is your message]
Note there is binary in the message returned, not handled by the Perl wrapper.
Have fun.