среда, 15 сентября 2010 г.

Пишем Jabber-клиент на Delphi. Часть 1

Введение

Jabber — система для быстрого обмена сообщениями и информацией о присутствии (в контакт-листе) между любыми двумя пользователями Интернета на основе открытого протокола XMPP.
В отличии от той же Аськи Jabber-сеть имеет на мой взгляд более развитые возможности, а наличие расширений протокола открывает горизонты функциональности на недосягаемые для коммерческих IM-сетей, вот некоторые из них:
Открытость: протокол Jabber открыт, общедоступен и достаточно лёгок для понимания; существует множество реализаций серверов и клиентов, а также библиотек с открытым исходным кодом.

Расширяемость: с помощью пространств имён в XML можно расширить протокол Jabber для выполнения требуемых задач и для обеспечения поддержки взаимодействия между различными системами. Общие расширения разрабатываются под контролем Jabber Software Foundation.
Децентрализованность: кто угодно может запустить свой собственный сервер Jabber, что позволяет организациям и частным лицам заниматься любыми экспериментами с IM.
Безопасность: любой сервер Jabber может быть изолирован от общедоступной сети Jabber, многие из вариантов реализации сервера используют SSL при обмене между клиентом и сервером, и немало клиентов поддерживают шифрование с помощью PGP/GPG внутри протокола.
Jabber удовлетворяет многие потребности частных лиц и организаций. Но важно понимать, что он не является универсальным решением всех задач. В частности, Jabber не является:
Универсальным чат-клиентом для различных систем IM — несмотря на множество клиентов Jabber под различные платформы, они не предоставляют таких возможностей по взаимодействию с различными системами IM, которые обеспечиваются программами Miranda IM, Trillian или Pidgin: вместо этого взаимодействие между Jabber и другими системами осуществляют шлюзы, расположенные на стороне сервера.
Универсальным решением проблем взаимодействия с различными IM-системами — некоторые сервера Jabber предоставляют возможность взаимодействия с другими системами IM через шлюзы, которые транслируют протокол Jabber в протокол этих систем; однако только от самих систем зависит осуществление взаимодействия (к чему они подчас не стремятся, и даже наоборот).

Основные сведения о протоколе XMPP.

В основе протокола XMPP (eXtensible Messaging and Presence Protocol) лежит язык XML. XMPP является открытым, свободным протоколом для мгновенного обмена сообщениями и информацией о присутствии в режиме околореального времени.
Изначально спроектированный легко расширяемым протокол помимо передачи текстовых сообщений поддерживает передачу голоса и файлов по сети.
Данный протокол принят как стандарт RFC.
Стандартный порт для Jabber-клиентов — 5222.
Протокол регламентируется следующими стандартами:
RFC 3920 - Extensible Messaging and Presence Protocol (XMPP): Core
RFC 3921 - Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence
Следует также отметить, так как протокол является текстовым, а не бинарным соответственно у этого протокола есть слабые стороны, а именно: избыточность передаваемой информации, отсутствие возможности передачи двоичных данных приводит к использованию различных способов перекодировки. В результате этого, для передачи файлов приходится использовать дополнительные протоколы, например HTTP. Если этого не избежать, то XMPP обеспечивает встроенную передачу файлов кодируя информацию используя base64. Другая двоичная информация, такая как закодированный разговор или графические иконки включаются с использованием такого же метода. Однако прежде чем двигаться дальше рассмотрим адресацию пользователей с Jabber-сетях.

Адресация пользователей в Jabber

Каждый пользователь в сети имеет уникальный идентификатор, адрес — Jabber ID (сокращённо JID). Во избежание необходимости существования сервера с полным списком всех адресов, JID подобно адресу электронной почты содержит имя пользователя (JID node) и DNS-адрес сервера (JID domain), на котором зарегистрирован пользователь, разделённые знаком (@). Например, пользователь user, зарегистрированный на сервере example.com, будет иметь следующий адрес (JID): user@example.com.
Также пользователь может подключаться, находясь в разных местах, сервер позволяет определять дополнительное значение, называемое ресурсом, который идентифицирует клиента пользователя в данный момент. Так можно включить в адрес пользователя (JID) имя его ресурса (JID resource), добавив через слэш в конце адреса.
К примеру, пусть полный адрес пользователя будет user@example.com/work, тогда сообщения, посланные на адрес user@example.com, дойдут на указанный адрес вне зависимости от имени ресурса, но сообщения для user@example.com/work дойдут на указанный адрес только при соответствующем подключённом ресурсе.
Адреса (JID) могут также использоваться без явного указания имени пользователя (с указанием имени ресурса или без такового) для системных сообщений и для контроля специальных возможностей на сервере.
Запомним эту информацию, она нам пригодятся в дальнейшем.

Структура XML-пакетов Jabber протокола (XML Streams)

Структура XML пакетов получаемых с сервера и передаваемых на него по спецификации RFC 3920 имеет следующий вид:
   |--------------------|

   | <stream>           |

   |--------------------|

   | <presence>         |

   |   <show/>          |

   | </presence>        |

   |--------------------|

   | <message to='foo'> |

   |   <body/>          |

   | </message>         |

   |--------------------|

   | <iq to='bar'>      |

   |   <query/>         |

   | </iq>              |

   |--------------------|

   | ...                |

   |--------------------|

   | </stream>          |

   |--------------------|

Как вы видите, на схеме представлена иерархическая структура XML подразделенная на следующие элементы, так называемый поток XML и элементы строф XML.
Поток XML – является контейнером для хранения элементов строф XML. Поток XML начинается с открытия тэга <STREAM> (с соответствующими атрибутами и пространством имен), конец потока XML заканчивается закрытием тега </STREAM>.  Во время обмена с сервером, клиент и сам сервер может посылать неограниченное количество элементов строф в потоке XML.
Строфы XML – это дискретные семантические модули представленные элементами, заключенными в потоке XML. Строфы XML являются дочерними  элементами (child node) корня XML <STREAM>. Начало любой строфы XML обозначено началом элемента (например, <PRESENCE>), конец строфы XML обозначен завершающим тегом (</PRESENCE>). В примере строфы XML: <PRESENCE>, <MESSAGE>, <IQ>. Каждая строфа XML представляет собой конкретную информацию, так например строфа <MESSAGE> представляет сообщение, а <IQ> информационный запрос.  Более подробно строфы будут рассмотрены далее.
Примечание: несмотря на стандарт, мной было замечено, что с некоторых серверов могут приходить пакеты, просто содержащие строфы XML, но включенные в поток XML. 

Атрибуты элементов XML

При приходе XML  у  тегов могут быть следующие основные атрибуты:
to – кому (JID).
From – откуда (JID).
Id – уникальный идентификатор, так называемый атрибут 'системы обнаружения атак'. Позволяет конкретно идентифицировать полученные данные. Рекомендовано делать его случайным. Но в принципе это не обязательно.
xml:lang – текущий язык, кодировка данных.
Version – версия.
Теги могут включать также и дополнительные атрибуты, зависящие от передоваемых данных.
Пример строфы <PRESENCE> с некоторыми атрибутами Вы можете увидеть ниже:
<presence from='delphi-test@jabber.ru/основная'
            to='delphi-test@jabber.ru/резервная'> 
  <show/>
</presence>

Пространства имен XML

Так как первоначально XMPP был задуман, как протокол, поддерживающий расширения, перед разработчиками встал вопрос, как можно реализовать данные расширения, не внося коррективы в основной протокол. И решение нашлось. Это решение – пространство имен, довольно известное в XML.
Пространство имён в XML — именованная совокупность имён элементов и атрибутов, служащая для обеспечения их уникальности в XML-документе. Все имена элементов в пределах пространства имён должны быть уникальны. Таким образом, реализуется различение одинаковых элементов XML или атрибутов. Для клиентов Jabber зарезервировано пространство имен “jabber:client”
Пространства имён объявляются с помощью зарезервированного XML атрибута xmlns, значение которого является названием пространства имен.
Например, элемент <QUERY> описанный пространством имен 'jabber:iq:roster' выглядит так:
 <query xmlns='jabber:iq:roster'>

 

Комментариев нет:

Отправить комментарий