Библиотек, позволяющих работать с сервисом Spread на CPAN можно найти немало. Основой для большинства является Spread, ориентированный еще на версию 3.x, который, однако, без проблем работает и с более новыми версиями сервера. Данный модуль предоставляет самый что ни наесть низкоуровневый интерфейс доступа со всеми вытекающими отсюда плюсами и минусами.
Для начала, давайте откроем соединение с сервером:
use Spread;
my ($mbox, $private_group) = Spread::connect({spread_name => '4803@localhost', private_name => 'perl_client'});
Конструктор имеет всего два параметра – spread_name – порт и адрес сервера, где запушен Spread и private_name – имя, под которым Вы будете зарегистрированы в системе. Это имя должно быть уникальным, в противном случае в соединении будет отказано.
Для того, чтобы начать работу, нужно подключиться к какой-нибудь группе:
Spread::join($mbox, 'test_group');
Что ж, вот мы и вошли, давайте отправим первое тестовое сообщение:
Spread::multicast($mbox, AGREED_MESS, 'test_group', 0, 'Hello to all');
Вот тут возникает целый ряд вопросов. Например, параметр номер два – это тип сообщения. Допускается применение следующих типов: UNRELIABLE_MESS, RELIABLE_MESS, FIFO_MESS, CAUSAL_MESS, AGREED_MESS, SAFE MESS. Например, если Вы отправляете сообщения с типом FIFO_MESS, они будут доставляться подписчикам строго в порядка их отправки(правила FIFO). А вот если Вам необходимо гарантировано доставить сообщение, лучше воспользоваться типами RELIABLE_MESS или SAFE_MESS. Более детально все типы описаны в данном руководстве.
Отправлять сообщения можно в несколько групп сразу, передав в качестве аргумента номер 3 массив с группами:
Spread::multicast($mbox, AGREED_MESS, @groups, 0, 'Hello to all');
Как видите, для отправки сообщений есть всего одна функция. Прием тоже не блещет особым разнообразием, да и смысла в этом нет. Для того, чтобы получить сообщение(если таковое есть), необходимо выполнить следующий вызов:
my($service_type, $sender, $groups, $mess_type, $endian, $message) = Spread::receive($mbox);
Данных вызов является блокирующим, так что если в очереди нет сообщения, программа или поток приостановит свое выполнение до того счастливого момента, когда новый message будет отправлен.
Блокировать выполнение не всегда нужно, иногда достаточно лишь подождать немного. Сделать это можно, передав в метод receive значение таймаута:
#Если сообщения нет в течении 2-х секунд, программа возобновляет выполнение
my($service_type, $sender, $groups, $mess_type, $endian, $message) = Spread::receive($mbox, 2);
Иногда нет возможности даже блокировать приложение на доли секунды, но проверить как-то состояние очереди надо. Для этих целей служим метод poll:
my $messagesize = Spread::poll($mbox);
if(defined($messagesize)){print "Получено $messagesize байт\n";}
Когда Ваше приложение заканчивает работу, рекомендую корректно отключиться от сервера, так как может возникнуть ситуация, что приложение вроде бы в отключке, а имя, под которым Вы вошли все еще используется. У меня такая ситуация возникала несколько раз, боролся я с ней сменой имен. Так что не забывайте про:
Spread::disconnect($mbox);
Последний, шестой, вызов Spread API – выход из группы:
Spread::leave($mbox, 'GroupA');
Как видите, ничего сложного тут нет, всего лишь несколько функций, зато какие можно творить чудеса! Посмотрите, сколько программного обеспечения использует Spread – количество модулей, так или иначе использующих Spread на CPAN превышает 90 штук, а это только для perl!
Кроме стандартного модуля Spread есть еще одна, достаточно неплохая библиотека для групповых коммуникаций – Spread::Message Основанная на Spread.pm, она предоставляет более расширенную функциональность, да еще и в ОО-стиле. Существуют высокоуровневые функции для работы с сообщениями, например, можно отправлять сложные структуры данных, такие как хеши:
use Spread::Message;
$mbox = Spread::Message->new(spread_name => '4803@localhost', group => ['my_test_group'], name => 'client_name', debug => 0);
$mbox->connect;
$mbox->sends('groupA', \%person);
Чтение комплексных структур осуществляется с помощью функции command:
my $person = $mbox->command;
Передача объектов хороша, когда все части написаны на perl, однако достаточно часто возникают ситуации, когда нужно заставить работать совместно конгломерат языков. Для решения этой задачи необходимо писать собственный сериализатор/десериализатор, причем под каждый из используемых языков программирования.
Мы используем достаточно простой, FIX-подобный протокол – ключ=значение сепаратор ключ=значение сепаратор ключ=значение... Конечно, все «игроки» должны иметь файл описания ключей. Приведу пример сообщения:
1=21|50=1004|61=1|51=dmcc123|55=1900210.0113|56=2112893.46|57=440000|59=0|60=380.20|58=1672893.46|2=16709|3=1004|4=55|9=8|5=1.5898|6=2007-07-10 22:39|7=1.5942|10=0|11=0.01|12=100000.0|13=2|14=16854|15=151004|16=3.0E-4|19=0.0|20=0.0|21=1.5942|22=0.0|23=1|24=0|17=-379.587999999997|18=0|200=2007/07/10|201=48|25=55|27=EURAUD|26=0|28=0|29=2000/10/10|30=1.5906|31=1.5921|1=21
Вот, кажется, и все. Дальше нужно действовать согласно рекомендации из манула - Understanding through practice ;)
Если у кого-то есть вопросы – обращайтесь, постараюсь помочь.

Спасибо тебе
Спасибо тебе Сергей, хорошо написал, у меня уже есть пара идей где это можно использовать....
Но у меня возник один вопрос:
в вызове multicast:
Spread::multicast($mbox, AGREED_MESS, @groups, 0, 'Hello to all');
что означает четвертый параметр, он всегда 0? я не особенно читал, только глянул документацию, но нигде пояснения не нашел... Тыкни носом плиз :) а лучше опиши здесь :)
----
Чтобы правильно задать вопрос, нужно знать больше половины ответа...
message_length. Для perl
message_length. Для perl это особо значения не имеет.
А MIME?
Я несколько не в теме... А если использовать для передачи объектов тот же base64 или QuotedPrint? Ведь по-моему именно эти методы применяются для отправки вложений в письмах и файлов в http? И модули под это дело имеются.
О теме
О каких именно объектах идет речь?
О файлах в частности
Я имел в виду файлы. А еще какие объекты можно передавать в рамках мгновенных сообщений?
Файл дробится
Файл дробится на фреймы и передается. Таким образом строят системы репликаций на spread или же вещания потокового видео.
Понятно, что дробится
Понятно, что дробится. Я не о том. Я о способах передачи файла как такового, или куска файла, или фрейма. Каким образом они передаются в spread? почему и привожу аналогию -- как оно происходит в http или в почте: сервер (или почтовый клиент) просто превращает файл в текст с помощью методов типа base64 и передает. А сколько кусков этого файло-текста получится -- зависит от объема самого файла. Может быть масса пакетов, это уже дело другого уровня. Ну или http сервер устанавливает флаг Transefer-Encoding: Chunk и передает файл порциями, указывая размер каждой порции в начале передачи
base64 уж слишком
base64 уж слишком толстый:) spread передает набор байт. Это может быть что угодно - строки, сериализованные объекты, части файла...Любой каприз:)