# Структура PDU в SMPP: заголовок и тело

> Каждое сообщение SMPP — это PDU (Protocol Data Unit) с фиксированным 16-байтовым заголовком, за которым следует тело, зависящее от операции. Заголовок — это четыре 4-байтовых целых числа в обратном порядке байтов: command_length, command_id, command_status и sequence_number. command_length учитывает весь PDU, включая заголовок, поэтому получатель сначала читает 4 байта, а затем остальное.

- Канонический URL: https://www.broadnet.me/ru/reference/smpp-pdu-anatomy
- Язык: ru
- Последнее обновление: 2026-07-18
- Издатель: BroadNet (https://www.broadnet.me)

Точная разбивка PDU SMPP по байтам: 16-байтовый заголовок (command_length, command_id, command_status, sequence_number), тело и способы кодирования полей.

## 16-байтовый заголовок

Каждый PDU начинается с одних и тех же четырёх беззнаковых 32-битных целых чисел в сетевом порядке байтов (big-endian). command_length — это полный размер PDU в октетах, включая эти 16 байт заголовка: анализатор читает первые 4 байта, узнаёт полную длину и затем читает остаток. command_id идентифицирует операцию. command_status равен 0 (ESME_ROK) в запросах и несёт код ошибки в ответах. sequence_number связывает запрос с его ответом.

*Поля заголовка SMPP (16 байт, big-endian)*

| Смещение | Поле | Размер | Назначение |
|---|---|---|---|
| 0 | command_length | 4 октета | Общая длина PDU в октетах, включая заголовок |
| 4 | command_id | 4 октета | Идентификатор операции (например, submit_sm = 0x00000004) |
| 8 | command_status | 4 октета | 0 в запросе; код ошибки в ответе |
| 12 | sequence_number | 4 октета | Сопоставляет запрос↔ответ (0x00000001–0x7FFFFFFF) |

## command_id и бит ответа

У каждой операции есть свой command_id. Соответствующий ответ использует то же значение со старшим битом, установленным в 1 (логическое ИЛИ с 0x80000000). Так, submit_sm — это 0x00000004, а submit_sm_resp — 0x80000004. generic_nack (0x80000000) — универсальный ответ об ошибке для неразбираемого или недопустимого PDU.

*Распространённые значения command_id*

| Операция | Запрос | Ответ |
|---|---|---|
| generic_nack | — | 0x80000000 |
| bind_receiver | 0x00000001 | 0x80000001 |
| bind_transmitter | 0x00000002 | 0x80000002 |
| query_sm | 0x00000003 | 0x80000003 |
| submit_sm | 0x00000004 | 0x80000004 |
| deliver_sm | 0x00000005 | 0x80000005 |
| unbind | 0x00000006 | 0x80000006 |
| replace_sm | 0x00000007 | 0x80000007 |
| cancel_sm | 0x00000008 | 0x80000008 |
| bind_transceiver | 0x00000009 | 0x80000009 |
| enquire_link | 0x00000015 | 0x80000015 |
| data_sm | 0x00000103 | 0x80000103 |

## Тело и кодирование полей

После заголовка следует тело, зависящее от операции, с обязательными параметрами, за которыми могут идти опциональные параметры TLV. SMPP использует три типа кодирования полей. Целые числа имеют фиксированный размер, беззнаковые, в обратном порядке байтов. C-Octet String — это ASCII-текст, завершаемый нулём (0x00), с объявленной максимальной длиной, включающей завершающий символ. Octet String — это поле необработанных байтов, длина которого задаётся предшествующим полем длины (например, short_message, размер которого задаётся sm_length).

*Типы кодирования полей SMPP*

| Тип | Кодировка |
|---|---|
| Integer | Фиксированные 1/2/4-октетные беззнаковые, big-endian (сетевой порядок байтов) |
| C-Octet String | ASCII с завершающим NUL; максимальная длина включает терминатор 0x00 |
| C-Octet String (Decimal/Hex) | Как указано выше, но с ограничением на десятичные или шестнадцатеричные цифры ASCII |
| Octet String | Необработанные байты; длина указывается отдельным полем длины, без терминатора |

## Разбор примера: submit_sm в канале

Минимальный PDU submit_sm. Значение command_length в заголовке (0x0000003D = 61) — это полный размер в байтах; command_id 0x00000004 — это submit_sm; command_status 0 обозначает запрос; sequence_number 0x0000000F связывает ответ. Далее следует тело в фиксированном порядке полей, определённом спецификацией.

*Заголовок submit_sm + начало тела (с пояснениями)*

```hex
00 00 00 3D   command_length = 61
00 00 00 04   command_id     = submit_sm
00 00 00 00   command_status = ESME_ROK (request)
00 00 00 0F   sequence_number = 15
-- body --
00            service_type    = "" (NULL)
05            source_addr_ton = 5 (alphanumeric)
00            source_addr_npi = 0 (unknown)
42 4E 00      source_addr     = "BN" + NULL
01            dest_addr_ton   = 1 (international)
01            dest_addr_npi   = 1 (E.164/ISDN)
...           destination_addr, esm_class, ... short_message
```

## Частые вопросы

### Включает ли command_length заголовок?

Да. command_length — это полная длина всего PDU в октетах, включая 16-байтовый заголовок. Получатель читает ровно command_length байт, чтобы извлечь один целый PDU из потока TCP.

### Какой порядок байтов использует SMPP?

Сетевой порядок байтов — big-endian — для всех многобайтовых целочисленных полей, включая каждое поле заголовка. 4-байтовое значение 61 передаётся как 00 00 00 3D.

### Как завершаются текстовые поля?

Текстовые поля — это C-Octet String: символы ASCII, завершаемые одним нулевым байтом (0x00). Пустая C-Octet String — это просто нулевой байт. Объявленная максимальная длина включает этот завершающий символ.

### Что такое generic_nack?

generic_nack (command_id 0x80000000) — это ответ, который получатель возвращает, когда PDU невозможно разобрать или он принципиально недопустим — например, при неверном command_length или неизвестном command_id. Его command_status несёт причину.

### Как получатель выделяет PDU из потока TCP?

TCP — это поток байтов без границ сообщений, поэтому получатель читает первые 4 байта, чтобы получить command_length, а затем читает указанное общее число байтов, чтобы выделить один полный PDU перед разбором остальной части заголовка и тела.

## Источники

- [SMPP v3.4 specification — §2, §3 PDU format](https://smpp.org/SMPP_v3_4_Issue1_2.pdf)
- [SMPP v5.0 specification](https://smpp.org/SMPP_v5.pdf)

## См. также

- [Обзор протокола SMPP](https://www.broadnet.me/ru/reference/smpp-protocol-overview)
- [Декодер PDU SMPP (бесплатный инструмент)](https://www.broadnet.me/ru/tools/smpp-pdu-decoder)
- [Опциональные параметры TLV в SMPP](https://www.broadnet.me/ru/reference/smpp-tlv-parameters)
- [Коды ошибок command_status в SMPP](https://www.broadnet.me/ru/reference/smpp-command-status-errors)
- [Документация для разработчиков](https://www.broadnet.me/ru/developers)
