Una integración SMPP robusta es cuestión de disciplina operativa, no solo de PDU correctas: elige el modo de bind adecuado, gestiona con cuidado el sequence_number y la ventana, reintenta con espera y variación aleatoria, haz el envío idempotente para evitar doble facturación, confirma cada deliver_sm y reconecta con limpieza ante fallos. Acierta en esto y los detalles del protocolo se resuelven solos.
bind_transceiverAbrir y autenticar la sesiónbind_transceiver_respSesión aceptadasubmit_smEnviar un mensajesubmit_sm_respAceptado, ID de mensaje devueltodeliver_smConfirmación de entrega o mensaje entrantedeliver_sm_respConfirmadoenquire_linkKeepalive en estado de inactividad
Estrategia de bind
Prefiere un bind transceiver cuando el proveedor lo permita, para que una conexión transporte envío y recepción y simplifique la correlación de DLR. Acuerda por escrito con el proveedor el número de bind simultáneos y el TPS por bind antes de escalar. Confirma la versión de SMPP negociada a partir del bind_resp, y gestiona los fallos de bind de forma explícita: reintenta estados transitorios de tipo ESME_RALYBND, pero trata ESME_RINVPASWD/ESME_RINVSYSID como errores fatales de configuración en lugar de repetir en bucle.
sequence_number y la ventana
Asigna un sequence_number monótonamente creciente (de 1 a 0x7FFFFFFF y luego reinicia) y úsalo para correlacionar cada respuesta con su solicitud. Registra las solicitudes pendientes en un mapa indexado por sequence_number con un tiempo de espera, para detectar una respuesta que nunca llega. Respeta la ventana: limita las PDU en vuelo sin confirmar y pausa los envíos cuando esté llena en lugar de disparar a ciegas, lo que provoca limitación.
| Estado | Por qué |
|---|---|
| Mapa de solicitudes pendientes (por sequence_number) | Correlacionar respuestas, detectar tiempos de espera agotados |
| Contador de ocupación de la ventana | Contrapresión antes de ESME_RTHROTTLED |
| Clave de idempotencia por mensaje lógico | Evitar envíos duplicados al reintentar |
| Estado del bind + hora del último enquire_link_resp | Detectar sesiones muertas |
Reintentos, espera e idempotencia
Reintenta los fallos transitorios (ESME_RMSGQFUL, ESME_RTHROTTLED, errores de sistema, tiempos de espera) con espera exponencial y variación aleatoria para que las tormentas de reconexión no se sincronicen entre trabajadores. No reintentes los errores permanentes (dirección no válida, contraseña no válida). Y lo crucial: haz el envío idempotente. Adjunta tu propia referencia (por ejemplo mediante user_message_reference) y deduplica, para que un reintento tras un tiempo de espera ambiguo no facture ni entregue dos veces.
Tratamiento de las confirmaciones de entrega
Solicita registered_delivery solo donde consumas los acuses. Responde siempre deliver_sm_resp con prontitud y procesa de forma asíncrona. Correlaciona los acuses con el TLV receipted_message_id, normalizando los formatos hexadecimal/decimal del identificador, y cierra un mensaje solo con un stat final. Asigna los códigos err de red a una taxonomía normalizada para que la calidad sea comparable entre rutas. Trata las notificaciones intermedias por separado de los estados terminales.
Keepalive y reconexión
Envía enquire_link con un temporizador de inactividad y trata una respuesta ausente como una sesión muerta. Ante cualquier desconexión, reconecta con espera y variación aleatoria en lugar de repetir en bucle. Al reconectar, reanuda desde un estado limpio: vuelve a hacer bind, reinicia el mapa de solicitudes pendientes y apóyate en la idempotencia para reenviar con seguridad lo que estuviera en vuelo. Instrumenta el estado del bind, la ocupación de la ventana, la latencia de envío/DLR y las tasas de códigos de error, y alerta sobre todos ellos.
Preguntas frecuentes
¿Cómo debo asignar el sequence_number?
Usa un contador monótonamente creciente de 1 hasta 0x7FFFFFFF y luego reinícialo. Mantén un mapa de sequence_number pendientes con tiempos de espera para correlacionar cada respuesta y detectar las solicitudes que nunca recibieron una.
¿Cómo evito la doble facturación en los reintentos?
Haz el envío idempotente. Adjunta tu propia referencia (p. ej. user_message_reference), deduplica con ella y diseña los reintentos para que un reenvío tras un tiempo de espera ambiguo se reconozca y suprima en lugar de entregarse y facturarse dos veces.
¿Qué errores de SMPP debo reintentar?
Reintenta los transitorios —ESME_RMSGQFUL, ESME_RTHROTTLED, errores de sistema y tiempos de espera— con espera exponencial y variación aleatoria. No reintentes los errores permanentes como ESME_RINVDSTADR o ESME_RINVPASWD; corrige la entrada o la configuración en su lugar.
¿Qué debo monitorizar en un bind SMPP?
El estado del bind, el tiempo desde el último enquire_link_resp, la ocupación de la ventana, la latencia de envío y DLR, y las tasas de error por código (especialmente ESME_RTHROTTLED). Alerta sobre el aumento de limitación o una ventana bloqueada como señales tempranas de problemas.
¿Cómo debo gestionar la reconexión tras una sesión caída?
Reconecta con espera exponencial y variación aleatoria, vuelve a hacer bind, reinicia tu mapa de solicitudes pendientes y reenvía los mensajes en vuelo apoyándote en la idempotencia para evitar duplicados. Nunca repitas reconexiones en bucle, que pueden hacer que bloqueen tu IP.
Especificaciones de la fuente
Las normas publicadas en las que se basa esta página. Se abre en una pestaña nueva.