Descripción general
SMPP es un protocolo de la industria de las telecomunicaciones, publicado por primera vez por Aldiscon/Logica a finales de la década de 1990 y actualmente mantenido por el foro de desarrolladores de SMPP. Define cómo dos pares intercambian unidades discretas llamadas PDU (Unidades de Datos de Protocolo) a través de una única conexión TCP: la aplicación se enlaza, envía mensajes, recibe confirmaciones, mantiene el enlace activo y se desvincula. Debido a que es binario y orientado a la conexión, soporta cargas de trabajo constantes de millones de mensajes al día con mucha menos sobrecarga que abrir una solicitud HTTP por mensaje. Lea esta página de principio a fin y comprenderá cada campo de una sesión SMPP real.
Qué es SMPP y dónde encaja
Una sesión SMPP siempre tiene dos roles. El ESME (Entidad Externa de Mensajería Corta) es su aplicación: una plataforma de SMS masivos, un servicio de OTP, un sistema de alertas. El SMSC (Centro de Servicio de Mensajes Cortos), llamado MC (Centro de Mensajes) en la v5.0, es el nodo del operador o agregador que almacena y reenvía mensajes hacia y desde los terminales a través de la red móvil. La ESME se conecta al SMSC; el SMSC se conecta a la red SS7 / núcleo móvil.
SMPP es la columna vertebral de A2P (De la aplicación a la persona) mensajería: códigos de verificación, recibos, alertas, marketing, en contraposición a P2P Mensajería de texto (de persona a persona) entre dos teléfonos móviles. El tráfico A2P es de alto volumen, generado por máquinas y basado en la confirmación de entrega, que es precisamente para lo que se diseñó SMPP.
¿Por qué un protocolo TCP binario en lugar de HTTP? Un único enlace SMPP es un socket de larga duración. Una vez abierto, se evita el establecimiento de conexión TCP y TLS por mensaje, se pueden tener muchos mensajes en tránsito simultáneamente (ventanas asíncronas), y el SMSC envía las confirmaciones de entrega y los mensajes entrantes directamente a través de la misma conexión. Con un alto rendimiento sostenido, esto resulta mucho más eficiente que una API HTTP de solicitud/respuesta, razón por la cual los operadores y los grandes remitentes lo estandarizan.
Historial de versiones
- SMPP v3.3 — la primera versión ampliamente desplegada; introdujo el conjunto principal de PDU, pero es anterior a los TLV (parámetros opcionales) y al enlace del transceptor.
- SMPP v3.4 — la versión dominante en producción actualmente. Se añadieron el enlace del transceptor, parámetros TLV opcionales, message_payload y data_sm. Casi todas las integraciones reales que desarrollarás utilizan la versión 3.4.
- SMPP v5.0 — La versión más reciente. Cambia el nombre de SMSC a MC, añade PDU de difusión (broadcast_sm), señalización de estado de congestión y TLV más estandarizados. Su adopción es limitada; primero se recomienda dar soporte a la versión 3.4 y considerar la versión 5.0 como opcional.
Arquitectura y tipos de bind
La topología es simple: el ESME abre una conexión TCP con el SMSC/MC y se autentica con un identificador. system_id y passwordLa dirección en la que la sesión puede transportar tráfico se fija en el momento de la vinculación eligiendo una de tres opciones. modos de enlaceCada modo es una PDU de enlace diferente.
Solo envío. El ESME puede enviar submit_sm, pero no puede recibir deliver_sm en esta sesión. Los recibos deben recibirse a través de un enlace de receptor independiente.
Solo recepción. El SMSC entrega deliver_sm (mensajes entrantes y DLR) al ESME, que no puede enviar mensajes en esta sesión.
En ambas direcciones durante una misma sesión: envío de SMS y recepción de SMS. Introducido en la versión 3.4 y recomendado como configuración predeterminada para nuevas integraciones.
Un cuarto actor es enrutamientoEl SMSC decide, para cada mensaje, qué ruta o interconexión de operador descendente sigue un mensaje enviado hacia el terminal de destino, y a qué ESME vinculado pertenece un mensaje entrante (originado en el móvil).
En la red, SMPP funciona sobre TCP. El puerto predeterminado registrado por IANA es 2775 para conexiones simples. SMPPS — SMPP envuelto en TLS — no tiene un puerto estándar único; los proveedores lo exponen en el puerto que elijan (en la práctica se ven los puertos 3550, 8775 y 2776). Siempre utilice el puerto cifrado que su proveedor le asigne para producción.
El ciclo de vida de la sesión
Cada sesión SMPP sigue el mismo proceso: apertura de TCP, enlace, mantenimiento de la conexión, intercambio de mensajes y confirmaciones, y, finalmente, desvinculación y cierre. El diagrama siguiente muestra una sesión completa de transceptor: cada fila representa una PDU, la azul que fluye desde el ESME al SMSC, y la verde, que fluye de vuelta.
Dos detalles importantes. Primero, submit_sm_resp Devuelve inmediatamente y solo significa “aceptado para entrega”; el resultado real llega más tarde como un deliver_sm recibo. En segundo lugar, cada PDU de solicitud tiene un recibo correspondiente. _resp que se hace eco de su sequence_number, que es como las respuestas asíncronas se correlacionan con las solicitudes.
Anatomía de la PDU
Todo en una conexión SMPP es un PDUCada PDU comienza con un valor fijo encabezado de 16 bytes de cuatro enteros de 4 bytes (32 bits, big-endian), seguidos de un cuerpo específico del comando. Lea primero el encabezado y sabrá exactamente cómo leer el resto.
| Compensar | Campo | Tamaño | Significado |
|---|---|---|---|
| 0–3 | longitud_del_comando | 4 bytes | Longitud total de la PDU completa en octetos, incluyendo el encabezado y el cuerpo. |
| 4–7 | id_de_comando | 4 bytes | ¿De qué operación se trata? (p. ej., submit_sm = 0x00000004). Las respuestas establecen el bit superior (0x80000000). |
| 8–11 | estado_comando | 4 bytes | 0 en las solicitudes; un código de resultado ESME_R* en las respuestas (0 = ESME_ROK = éxito). |
| 12–15 | número_de_secuencia | 4 bytes | El llamador asignó el ID 1…0x7FFFFFFF; la respuesta _resp correspondiente lo reproduce para correlacionarlos. |
| 16… | cuerpo | variable | Parámetros obligatorios para este comando, y luego cualquier parámetro TLV opcional. |
El cuerpo termina con cualquier número de TLV — Parámetros opcionales Codificados como Etiqueta (2 bytes), Longitud (2 bytes), Valor (Length bytes). Los TLV son la forma en que la versión 3.4 extendió el protocolo sin afectar a las versiones anteriores: message_payload, receipted_message_id, campos de concatenación sar_* y muchos más se transmiten como TLV.
El número_de_secuencia es la clave para el uso de ventanas. Debido a que SMPP es asíncrono, un ESME puede enviar muchas PDU submit_sm —cada una con un número de secuencia incremental— antes de que lleguen las respuestas. Cuando las PDU submit_sm_resp regresan, su número de secuencia indica a qué envío responde cada una. El número de PDU no confirmadas permitidas en tránsito es el tamaño de la ventana.
Referencia de PDUs principales
Estas son las operaciones que realmente utilizará. Cada solicitud tiene una PDU de respuesta cuyo command_id es el id de la solicitud con el bit más significativo activado (0x80000000), por lo que submit_sm 0x00000004 se corresponde con submit_sm_resp 0x80000004.
| PDU | id_de_comando | Objetivo |
|---|---|---|
| bind_receiver | 0x00000001 | Abra una sesión de solo recepción. |
| bind_transmitter | 0x00000002 | Abrir una sesión solo para enviar mensajes. |
| bind_transceiver | 0x00000009 | Abrir una sesión bidireccional (v3.4). |
| submit_sm | 0x00000004 | Enviar un único mensaje a un único destino. |
| submit_multi | 0x00000021 | Envía un mensaje a hasta 254 destinos. |
| deliver_sm | 0x00000005 | SMSC → ESME : una confirmación de entrega o mensaje entrante (MO). |
| data_sm | 0x00000103 | Alternativa bidireccional exclusiva para TLV a submit_sm / deliver_sm. |
| query_sm | 0x00000003 | Solicita al SMSC el estado actual de un mensaje enviado. |
| cancel_sm | 0x00000008 | Cancelar un mensaje enviado previamente pero aún no entregado. |
| replace_sm | 0x00000007 | Reemplazar el contenido/horario de un mensaje pendiente. |
| enquire_link | 0x00000015 | Mantener la sesión activa: confirma que la sesión sigue en curso. |
| unbind | 0x00000006 | Cierre correctamente la sesión SMPP. |
| generic_nack | 0x80000000 | Acuse de recibo negativo para una PDU no analizable/no válida. |
submit_sm campo por campo
submit_sm Es la PDU que enviará con mayor frecuencia. Su cuerpo es una secuencia de parámetros obligatorios y TLV opcionales. Estos son los campos que importan en la práctica.
| Campo | Lo que hace |
|---|---|
| service_type | Categoría de aplicación SMS opcional (por ejemplo, en blanco o un valor que su SMSC utilice para las clases de enrutamiento/facturación). |
| source_addr_ton / _npi | Tipo de número e indicador del plan de numeración para el remitente. TON 5 = alfanumérico (un ID de remitente); TON 1 = internacional E.164. |
| source_addr | La dirección del remitente: un código corto, un número largo o un identificador de remitente alfanumérico de hasta 11 caracteres. |
| dest_addr_ton / _npi | TON / NPI para el destino. Normalmente TON 1 (internacional), NPI 1 (ISDN / E.164). |
| destination_addr | El MSISDN del destinatario, normalmente en formato internacional sin un + inicial. |
| esm_class | Máscara de bits de modo/tipo de mensajería: por ejemplo, la solicitud de una confirmación de entrega es gestionada por registered_delivery, mientras que el bit UDHI (0x40) indica que short_message comienza con un UDH. |
| data_coding | El DCS : 0 = GSM de 7 bits (predeterminado), 3 = Latin-1, 8 = UCS-2 (Unicode). Controla el límite de caracteres. |
| registered_delivery | Establezca el valor en 1 para solicitar un comprobante de entrega (deliver_sm) para este mensaje; 0 para no solicitar ningún comprobante. |
| sm_length / short_message | La longitud de la carga útil (0–254) y los octetos del mensaje en sí, codificados por data_coding. |
| message_payload (TLV 0x0424) | TLV opcional que contiene el cuerpo del mensaje en lugar de short_message; se utiliza para contenido largo que supera los 254 octetos. |
| schedule_delivery_time / validity_period | Tiempo absoluto/relativo opcional para programar la entrega y cuánto tiempo debe seguir intentándolo el SMSC. |
Codificación y concatenación de datos
El data_coding El campo (el Esquema de Codificación de Datos, DCS) le indica al terminal cómo interpretar los bytes y decide cuántos caracteres caben en un SMS.
| codificación de datos | Codificación | Soltero | Concatenado |
|---|---|---|---|
| 0 | Alfabeto predeterminado GSM de 7 bits | 160 caracteres | 153 caracteres / parte |
| 3 | Latin-1 (ISO-8859-1), 8 bits | 140 caracteres | 134 caracteres / parte |
| 8 | UCS-2 (UTF-16BE) — Unicode | 70 caracteres | 67 caracteres / parte |
Un mensaje de más de un segmento se divide y se vuelve a ensamblar en el terminal mediante un UDH (Encabezado de datos de usuario) antepuesto a cada parte. El elemento de concatenación utiliza IEI 0x00 (referencia de 8 bits): un encabezado de 6 octetos que contiene un número de referencia, el número total de partes y el índice de esta parte. Esos 6 octetos son la razón por la que los límites por parte bajan a 153 (GSM de 7 bits) y 67 (UCS-2). Cuando envíe un UDH dentro de short_message, también debe activar el bit UDHI (0x40) en esm_class.
Hay dos maneras de enviar contenido largo: crear usted mismo las partes segmentadas por UDH (cada una un submit_sm con UDHI configurado), o entregar el cuerpo completo al SMSC en el message_payload TLV y permite la segmentación. Algunos SMSC aceptan en cambio los TLV sar_msg_ref_num / sar_total_segments / sar_segment_seqnum para describir la concatenación sin UDH.
Comprobantes de entrega (DLR)
Cuando lo configures registered_delivery = 1El SMSC informa posteriormente del destino del mensaje enviándote un correo electrónico. deliver_sm con el bit de confirmación de entrega activado en esm_class (0x04El texto del recibo se encuentra en el campo short_message como una cadena de palabras clave conocida:
id:1a2b3c4d5e sub:001 dlvrd:001 submit date:2607251432 done date:2607251432 stat:DELIVRD err:000 text:Your code is 8El id coincide con el message_id que recibió de vuelta en submit_sm_resp (también reflejado en el TLV 0x001E de receipted_message_id). El stat El campo contiene el estado final:
| estadística | Significado |
|---|---|
| DELIVRD | Entregado al dispositivo. Estado de éxito. |
| EXPIRED | El período de validez expiró antes de la entrega; el SMSC dejó de intentarlo nuevamente. |
| DELETED | El mensaje fue eliminado en el SMSC. |
| UNDELIV | No se pudo entregar el paquete: no hay ruta disponible o no se pudo contactar con el teléfono. |
| ACCEPTD | Aceptado (por ejemplo, leído manualmente en el SMSC): un estado intermedio. |
| UNKNOWN | El SMSC no tiene información de estado para el mensaje. |
| REJECTD | Rechazado por el SMSC o por una red descendente (por ejemplo, remitente bloqueado). |
Siempre responde a un deliver_sm con un deliver_sm_respSi no lo hace, el SMSC reenviará el recibo y podría limitar o cancelar la conexión. Tenga en cuenta que el formato del recibo no está perfectamente estandarizado: los proveedores varían ligeramente en el orden de los campos y en el mapa de códigos de error.
Códigos de error / estado del comando
Cada PDU de respuesta lleva un command_status en su encabezado — un ESME_R* Código. Cero significa éxito; cualquier otro valor describe el motivo del rechazo de la solicitud. Estos son los códigos que encontrará con mayor frecuencia.
| Código | Valor | Significado |
|---|---|---|
| ESME_ROK | 0x00000000 | Sin errores: éxito. |
| ESME_RINVMSGLEN | 0x00000001 | Longitud de mensaje no válida (problema sm_length / payload). |
| ESME_RINVCMDLEN | 0x00000002 | command_length no válida: el encuadre de la PDU es incorrecto. |
| ESME_RINVCMDID | 0x00000003 | command_id desconocido o no compatible. |
| ESME_RINVBNDSTS | 0x00000004 | El comando no es válido en el estado de enlace actual (por ejemplo, enviar en un enlace RX). |
| ESME_RALYBND | 0x00000005 | ESME ya está vinculada. |
| ESME_RINVSRCADR | 0x0000000A | Dirección de origen no válida (ID del remitente). |
| ESME_RINVDSTADR | 0x0000000B | Dirección de destino no válida. |
| ESME_RBINDFAIL | 0x0000000D | Error de conexión: system_id / contraseña incorrectos. |
| ESME_RINVPASWD | 0x0000000E | Contraseña incorrecta. |
| ESME_RTHROTTLED | 0x00000058 | Error de limitación de velocidad: ha superado la tasa de mensajes permitida. |
| ESME_RSUBMITFAIL | 0x00000045 | submit_sm / submit_multi falló. |
| ESME_RSYSERR | 0x00000008 | Error del sistema SMSC. |
El registro completo, incluyendo los rangos de proveedores específicos, se puede buscar en el Referencia de códigos de error SMPP.
Rendimiento, segmentación y limitación de velocidad
El rendimiento en SMPP se mide en TPS — transacciones (submit_sm) por segundo — y está regido por dos cosas: la tasa que permite el SMSC y cuántos mensajes mantienes en tránsito. Como SMPP es asíncrono, no tienes que esperar a cada submit_sm_resp antes de enviar la siguiente PDU. El número de envíos no confirmados que permites a la vez es tu tamaño de la ventana (generalmente entre 10 y 100). Un rango mayor oculta la latencia de ida y vuelta y aumenta el TPS efectivo, hasta el límite máximo del SMSC.
- Respeta el acelerador. Cuando el SMSC devuelva ESME_RTHROTTLED (0x58), espere: haga una pausa y vuelva a intentarlo con retroceso exponencial en lugar de saturar el enlace, lo que puede provocar una desconexión.
- Mantener la conexión a un ritmo determinado. Envía un enlace de consulta aproximadamente cada 30 segundos mientras estés inactivo; si algunos mensajes quedan sin respuesta, asume que el enlace no funciona.
- Reconectar deliberadamente. Al desconectarse, vuelva a conectar y vuelva a vincular con retroceso y fluctuación; no utilice bucles cerrados. Registre los números de secuencia pendientes para poder conciliar las recepciones después de una reconexión.
- Escalar con ataduras, con cuidado. Un mayor TPS agregado generalmente proviene de múltiples vinculaciones, pero solo hasta el límite que su proveedor autoriza por cuenta.
Ejemplo de código
Un ejemplo ilustrativo del flujo de conexión → enlace → envío en pseudocódigo estilo Node. Las bibliotecas SMPP reales (por ejemplo, node-smpp, jSMPP para Java o python-smpplib) se encargan de la codificación de PDU; esto muestra la estructura de la sesión, no la API de una biblioteca específica.
import smpp from "smpp";
// 1. Open a TCP (or TLS) session to the SMSC.
const session = smpp.connect({
// Host, port and bind credentials come with your test access.
// Plain SMPP conventionally uses 2775; the TLS port is provided with your account.
url: process.env.SMPP_URL!, // e.g. smpp://<host>:2775 (plain) or smpps://<host>:<tls-port>
auto_enquire_link_period: 30000, // keepalive every 30s
});
// 2. Bind as a transceiver.
session.bind_transceiver(
{
system_id: "YOUR_SYSTEM_ID",
password: "YOUR_PASSWORD",
system_type: "",
},
(pdu) => {
if (pdu.command_status !== 0) {
throw new Error("bind failed: 0x" + pdu.command_status.toString(16));
}
// 3. Submit a Unicode message, asking for a delivery receipt.
session.submit_sm(
{
source_addr_ton: 5, // alphanumeric Sender ID
source_addr: "BroadNet",
dest_addr_ton: 1, // international E.164
destination_addr: "447700900123",
registered_delivery: 1, // request a DLR
data_coding: 8, // UCS-2 (Unicode)
short_message: "Your code is 8123",
},
(submitResp) => {
// submit_sm_resp returns the SMSC message_id.
console.log("accepted, message_id =", submitResp.message_id);
}
);
}
);
// 4. Receive delivery receipts on the same session.
session.on("deliver_sm", (pdu) => {
if ((pdu.esm_class & 0x04) === 0x04) { // delivery-receipt bit
console.log("DLR:", pdu.short_message.message);
}
session.send(pdu.response()); // ALWAYS deliver_sm_resp
});BroadNet SMPP
BroadNet opera una pasarela SMSC de nivel operador que acepta enlaces SMPP v3.4 sobre TLS. Obtendrá: enlaces de transceptor, alto TPS con ventanas asíncronas, confirmaciones de entrega completas, Unicode y concatenación, y una conexión con credenciales y lista de direcciones IP permitidas para comunicarse con operadores de todo el mundo. Es el mismo protocolo que se enseña en esta página, configurado para rutas reales.
Solicita la configuración de tu cuenta y nuestro equipo de ingeniería de ventas configurará tu system_id, punto final TLS, TPS y lista de direcciones IP permitidas. También puedes consultar cómo se construye la pasarela.
Preguntas frecuentes
¿Qué puerto utiliza SMPP?
El puerto TCP 2775, registrado por IANA, es el predeterminado para SMPP estándar. No existe un único puerto TLS estándar: SMPPS (SMPP sobre TLS) suele funcionar en un puerto específico del proveedor, como el 3550, el 8775 o el 2776. Por lo tanto, utilice siempre el puerto que le asigne su operador de SMSC. BroadNet publica su host de enlace, puerto estándar y puerto TLS junto con sus credenciales.
¿Cuál es la diferencia entre submit_sm y data_sm?
submit_sm es la PDU principal que un ESME utiliza para enviar un único mensaje corto; contiene el campo short_message clásico (hasta 254 octetos) más TLV opcionales. data_sm es una alternativa simétrica y optimizada introducida en SMPP v3.4 que siempre contiene el contenido del TLV message_payload y puede fluir en cualquier dirección (ESME→SMSC o SMSC→ESME). La mayoría del tráfico A2P utiliza submit_sm; data_sm se utiliza cuando se prefiere su formato bidireccional basado únicamente en TLV.
¿Cómo gestiona SMPP Unicode?
Unicode se envía configurando data_coding en 8 (UCS-2 / UTF-16BE big-endian). Un segmento UCS-2 contiene 70 caracteres; las partes UCS-2 concatenadas contienen 67 caracteres cada una, ya que el encabezado de concatenación UDH consume 6 octetos. GSM de 7 bits (data_coding 0) es el valor predeterminado para texto latino básico de 160/153 caracteres.
¿Qué es una vinculación de transceptor?
Un enlace de transceptor (TRX) es una única sesión SMPP, que se abre con `bind_transceiver`, y que puede tanto enviar mensajes (`submit_sm`) como recibir mensajes y confirmaciones de entrega (`deliver_sm`) a través de la misma conexión TCP. Sustituye al antiguo método de abrir un enlace de transmisor y un enlace de receptor por separado, y es el modo recomendado para la mayoría de las integraciones modernas.
¿Por qué utilizar SMPP en lugar de una API HTTP?
SMPP es un protocolo TCP binario persistente diseñado para un alto rendimiento sostenido. Su enlace de larga duración evita los intercambios de mensajes TLS/TCP, admite ventanas asíncronas (muchos mensajes submit_sm pendientes antes de un ack) y entrega recibos deliver_sm en tiempo real y mensajes originados en dispositivos móviles a través del mismo socket. Para volúmenes A2P muy altos y constantes, es más eficiente que HTTP de solicitud/respuesta; HTTP REST es más sencillo para volúmenes menores y canales más complejos.
¿Qué es enquire_link?
`enquire_link` es una PDU de mantenimiento de conexión ligera que cualquiera de los pares envía para confirmar que la sesión SMPP y la conexión TCP subyacente siguen activas; el otro extremo responde con `enquire_link_resp`. Normalmente se envía cada 30 segundos durante los periodos de inactividad. Si varios mensajes de `enquire_link` quedan sin respuesta, el par considera que el enlace está inactivo y se reconecta.
¿Qué significa command_length en una cabecera PDU?
command_length es el primer campo de 4 bytes de cada encabezado PDU SMPP y contiene la longitud total de la PDU completa en octetos, incluyendo el encabezado de 16 bytes y el cuerpo completo. Un receptor lee primero estos 4 bytes para saber exactamente cuántos bytes más debe leer para obtener la PDU completa antes de analizar command_id, command_status y sequence_number.
¿Qué es una confirmación de entrega (DLR) en SMPP?
Una confirmación de entrega es la notificación que el SMSC le da al ESME sobre el destino final de un mensaje enviado. Llega como una PDU deliver_sm con el bit de confirmación de entrega esm_class activado (0x04). El short_message contiene una cadena de confirmación de entrega con palabras clave: id, sub, dlvrd, fecha de envío, fecha de entrega, stat y err, donde stat indica el estado final, como DELIVRD, EXPIRED, UNDELIV o REJECTD.