On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru






 

SMS-приложение. Часть 1

С.Кадаков

Глава 1 Выбор протокола.

Что ж, вот и настала пора написать наше первое реально работающее SMS-приложение, чем и займемся. Для "удобоварения" мы разбили эту статью на несколько частей: сначала займемся некоторыми теоретическими вопросами (так, сущие пустяки -- опишем протокол :), а затем, не отвлекаясь, займемся кодированием.

В прошлый раз мы показали, как устанавливать связь с Сервис-центром, теперь же необходимо научиться работать собственно с протоколом -- формировать и "разбирать" пакеты. Но прежде, как легко догадаться, необходимо выбрать протокол. Эту сложнейшую задачу мы возьмем на себя ;) и остановимся на SMPP (Short Messages Peer-to-Peer). В пользу такого выбора говорят не только личные пристрастия, но и то, что данный протокол является наиблее широко распространненым, отлично проработан и превосходно документирован. Кроме того, не исключая возможности того, что читателям в реальности придется столкнуться с другими протоколами, отметим, что здесь ситуация сродни изучению иностранных языков: второй изучать легче чем первый, третий, чем второй и т. д.

Глава 2. Протокол SMPP.

Обзор.

Протокол SMPP позволяет , как не трудно догадаться, "внешним" устройствам обмениваться сообщениями с мобильной сетью (PLMN) посредством SMSC и определяет:

  • Набор операций для обмена между SMSC и ESME, называемых также "командами" (command).
  • Формат передаваемого пакета (PDU -- Protocol Data Unit), ассоциированный с каждой из операций.
  • Формат ответного пакета (ACK или responce) для каждой PDU.
  • Данные, которыми ESME должна обмениваться с SMSC в ходе таких операций.

Таким образом, вызову команды соответствует отправка PDU, поэтому мы иногда вместо "вызвать submit_sm" будем говорить "послать submit_sm" и наоборот. Следует также обратить внимание на то, что каждая из команд в рамках сессии должна быть подтверждена ответным пакетом (ACK), единственное исключение -- alert_notification PDU (впрочем, эта команда нам на первых порах не понадобится).

Сессии SMPP.

Обмен сообщениями с SMSC в формате протокола SMPP (кстати говоря -- не только) носит сессионный характер. Это означает, что обмен должен предваряться некоторой процедурой инициализации сессии и, в безошибочном варианте, за обменом должна следовать процедура закрытия сессии. В ходе процедуры открытия сессии ESME открывает соединение на уровне сокета, авторизуется и сообщает о цели открытия сессии:

  • Прием сообщений. (приемник -- RECEIVER)
  • Передача сообщений. (передатчик -- TRANSMITTER)
  • Прием и передача сообщений. (приемо-передатчик -- TRANCEIVER)

Процедура инициализации выполняется с помощью вызова одной из команд bind_*:

  • bind_receiver
  • bind_transmitter
  • bind_tranceiver
формат которых мы рассмотрим чуть ниже. Таким образом, сессия может находиться в следующих состояниях:
  • OPEN -- Установлено сокетное соединение и послан один из запросов bind_*.
  • BOUND_RX | BOUND_TX | BOUND_TRX -- Выполнена одна из команд bind_*. Соединение готово к приему | передаче | приему и передаче.
  • CLOSED -- Выполнена команда unbind (рассмотрим позже) и соединение закрыто.
Кроме того, SMSC в любой момент может послать команду outbind. В ответ на эту команду ESME обязана снова выполнить один из запросов bind_*. Правда, в реальной практике эта команда встречается редко, но к ее обработке следует быть готовым.

Команды (PDU) SMPP

Протокол SMPP версии 3.4 предоставляет следующий набор команд:


SMPP PDU Name Required SMPP Session State Issued by ESME Issued by SMSC
bind_transmitter OPEN Yes No
bind_transmitter_resp OPEN No Yes
bind_receiver OPEN Yes No
bind_receiver_resp OPEN No Yes
bind_transceiver OPEN Yes No
bind_transceiver_resp OPEN No Yes
outbind OPEN No Yes
unbind BOUND_TX
BOUND_RX
BOUND_TRX
Yes
Yes
Yes
Yes
Yes
Yes
unbind_resp BOUND_TX
BOUND_RX
BOUND_TRX
Yes
Yes
Yes
Yes
Yes
Yes
submit_sm BOUND_TX
BOUND_TRX
Yes
Yes
No
No
submit_sm_resp BOUND_TX
BOUND_TRX
No
No
Yes
Yes
submit_sm_multi BOUND_TX
BOUND_TRX
Yes
Yes
No
No
submit_sm_multi_resp BOUND_TX
BOUND_TRX
No
No
Yes
Yes
data_sm BOUND_TX
BOUND_RX
BOUND_TRX
Yes
Yes
Yes
Yes
Yes
Yes
data_sm_resp BOUND_TX
BOUND_RX
BOUND_TRX
Yes
Yes
Yes
Yes
Yes
Yes
deliver_sm BOUND_RX
BOUND_TRX
No
No
Yes
Yes
deliver_sm_resp BOUND_RX
BOUND_TRX
Yes
Yes
No
No
query_sm BOUND_TX
BOUND_TRX
Yes
Yes
No
No
query_sm_resp BOUND_TX
BOUND_TRX
No
No
Yes
Yes

Команды с суффиксом _resp означают responce, т. е. ACK (мы также употребляем термин квитанция, и говорим, что ACK "квитирует" команду). Жирным помечены команды, которые мы рассмотрим (остальные в нашем простейшем случае нам пока не понадобятся).

Режимы (Modes) сообщений.

Протокол SMPP v3.4 поддерживает три режима обмена сообщениями. Мы не будем на этом особо останавливаться, просто упомянем, что в дальнейшем будем работать в т. н. Store and Forward Message Mode. В данном режиме сообщение сначала сохраняется в базе данных SMSC, а потом предпринимаются попытки его доведения, и, в зависимости от запроса, ESME уведомляется о достижении сообщением финального состояния (доведено/не доведено). Поддерживаются также Datagram Mode и Transaction Mode, о которых можно прочесть в соответствующей документации.

Типы данных SMPP

Все определяемые протоколом PDU представляют собой совокупность полей определенных типов, выстроенные друг за другом в определенном порядке. При работе в сети принято использовать понятие октет (octet) -- совокупность восьми битов (то что принято называть в программировании байтом) для того, чтобы подчеркнуть "восьмибитовость". Все определяемые SMPP типы привязаны к октету. Вот они:

  • Integer -- Беззнаковое целое с указанной в каждом конкретном случае длиной в октетах.
  • C-Octet String -- Серия ASCII литер, завершенная нулем.
  • C-Octet String (Decimal) -- Серия литер (0-9), завершенная нулем
  • C-Octet String (Hex) -- Серия литер (0-F), завершенная нулем.
  • Octet String -- Серия октетов, не обязятельно завершенная нулем.
  • TLV -- Tag-Length-Value. Используется для необязательных параметров. Данный тип возник из-за необходимость расширять уже существующие команды с сохранением обратной совместимости.Поскольку мы не собираемся таковые использовать :), то и останавливаться на этом не будем, хотя вопрос, вообще говоря, важный. Про TLV можно прочитать в спецификации протокола.

Формат PDU

Каждый пакет (PDU) состоит из двух частей:

  1. Заголовок (header). Обязательная.
  2. Тело (body). Необязательная.
Формат заголовка общий для всех PDU.

Заголовок (header)

Заголовок имеет длину 16 октетов и состоит из 4-х полей:

  1. Command length -- Длина. 4 октета. Должен содержать общую длину пакета, включая и это поле.
  2. Command id -- Идентификатор команды. 4 октета. Указывает на тип команды. Принимает значения от 0x0 до 0x1FF для команд и от 0x800000000 до 0x8000001FF для ответов (ACK). Каждый пакет, представляющий собой ACK имеет command_id такой же, как и квитируемая команда, но с выставленным 31-м битом
  3. Command status -- Статус команды. 4 октета. Используется в ACK'ах, в командах выставляется в 0x0.
  4. Sequence number -- Номер последовательности. В каждом конкретном случае содержит уникальный номер отдельной команды (не путать с command_id) и позволяет ассоциировать ACK с командой. Назначается испускающей стороной произвольно из диапазона 0x1-0x7FFFFFFF. Повтор данного номера в рамках одной сессии, вообще говоря, не допустим. ACK должен иметь тот же номер, что и квитируемая команда.
Некоторые PDU (в частности, большинство ACK'ов) состоят только из заголовка и этой информации оказывается достаточно.

Глава 3. Промежуточный итог

В данной части мы обсудили исключительно важный вопрос, а именно: структуру протокола. Надеемся, пока недоразумений не возникло.



Языки программирования: разное