Une intégration SMPP robuste tient à la discipline opérationnelle, pas seulement à des PDU correctes : choisir le bon mode de bind, gérer soigneusement le sequence_number et la fenêtre, réémettre avec temporisation à gigue, rendre la soumission idempotente pour éviter la double facturation, acquitter chaque deliver_sm, et se reconnecter proprement en cas d'échec. Réussissez cela et les détails du protocole se règlent d'eux-mêmes.
bind_transceiverOuvrir et authentifier la sessionbind_transceiver_respSession acceptéesubmit_smEnvoyer un messagesubmit_sm_respAccepté, ID du message renvoyédeliver_smAccusé de réception ou message entrantdeliver_sm_respConfirméenquire_linkKeepalive en cas d'inactivité
Stratégie de bind
Privilégiez un bind transceiver quand le fournisseur l'autorise, pour qu'une seule connexion porte l'émission et la réception et simplifie la corrélation des DLR. Convenez par écrit du nombre de binds simultanés et du TPS par bind avec le fournisseur avant de monter en charge. Confirmez la version SMPP négociée depuis le bind_resp, et gérez les échecs de bind explicitement — réémettez sur les états transitoires de type ESME_RALYBND, mais traitez ESME_RINVPASWD/ESME_RINVSYSID comme des erreurs de configuration fatales plutôt que de boucler.
sequence_number et la fenêtre
Attribuez un sequence_number monotone croissant (1 à 0x7FFFFFFF, puis rebouclage) et utilisez-le pour corréler chaque réponse à sa requête. Suivez les requêtes en attente dans une table indexée par sequence_number avec un délai d'expiration, afin de détecter une réponse qui n'arrive jamais. Respectez la fenêtre : plafonnez les PDU non acquittées en vol et suspendez les submits quand elle est pleine plutôt que d'émettre à l'aveugle, ce qui déclenche le throttling.
| État | Pourquoi |
|---|---|
| Carte des requêtes en attente (par sequence_number) | Corréler les réponses, détecter les délais d'attente |
| Compteur d'occupation de la fenêtre | Contre-pression avant ESME_RTHROTTLED |
| Clé d'idempotence par message logique | Empêcher les envois en double lors de la nouvelle tentative |
| État du bind + heure du dernier enquire_link_resp | Détecter les sessions inactives |
Réémissions, temporisation et idempotence
Réémettez les échecs transitoires (ESME_RMSGQFUL, ESME_RTHROTTLED, erreurs système, expirations) avec temporisation exponentielle et gigue pour que les tempêtes de reconnexion ne se synchronisent pas entre workers. Ne réémettez pas les erreurs permanentes (adresse invalide, mot de passe invalide). Surtout, rendez la soumission idempotente : attachez votre propre référence (par exemple via user_message_reference) et dédupliquez, pour qu'une réémission après une expiration ambiguë ne facture ni ne remette deux fois.
Gestion des accusés de réception
Ne demandez registered_delivery que là où vous consommez les accusés. Répondez toujours rapidement par deliver_sm_resp et traitez de façon asynchrone. Corrélez les accusés sur le TLV receipted_message_id, en normalisant les formats hexadécimal/décimal de l'id, et ne clôturez un message que sur un stat final. Faites correspondre les codes err réseau à une taxonomie normalisée pour que la qualité soit comparable entre routes. Traitez les notifications intermédiaires séparément des états terminaux.
Maintien de session et reconnexion
Envoyez enquire_link sur un minuteur d'inactivité et traitez une réponse manquante comme une session morte. À toute déconnexion, reconnectez-vous avec temporisation et gigue plutôt qu'en bouclant à chaud. À la reconnexion, repartez d'un état propre : refaites le bind, réinitialisez la table des requêtes en attente, et appuyez-vous sur l'idempotence pour resoumettre sans risque ce qui était en vol. Instrumentez l'état du bind, l'occupation de la fenêtre, la latence submit/DLR et les taux de codes d'erreur, et alertez sur chacun.
Questions fréquemment posées
Comment attribuer le sequence_number ?
Utilisez un compteur monotone croissant de 1 jusqu'à 0x7FFFFFFF, puis rebouclez. Conservez une table des sequence_number en attente avec des délais d'expiration afin de corréler chaque réponse et de détecter les requêtes restées sans réponse.
Comment éviter la double facturation lors des réémissions ?
Rendez la soumission idempotente. Attachez votre propre référence (par ex. user_message_reference), dédupliquez dessus, et concevez les réémissions pour qu'un renvoi après une expiration ambiguë soit reconnu et supprimé plutôt que remis et facturé deux fois.
Quelles erreurs SMPP faut-il réémettre ?
Réémettez les erreurs transitoires — ESME_RMSGQFUL, ESME_RTHROTTLED, erreurs système et expirations — avec temporisation exponentielle et gigue. Ne réémettez pas les erreurs permanentes comme ESME_RINVDSTADR ou ESME_RINVPASWD ; corrigez plutôt l'entrée ou la configuration.
Que surveiller sur un bind SMPP ?
L'état du bind, le temps depuis le dernier enquire_link_resp, l'occupation de la fenêtre, la latence submit et DLR, et les taux d'erreur par code (surtout ESME_RTHROTTLED). Alertez sur une hausse du throttling ou une fenêtre bloquée comme signaux précoces de problème.
Comment gérer la reconnexion après une session tombée ?
Reconnectez-vous avec temporisation exponentielle à gigue, refaites le bind, réinitialisez votre table des requêtes en attente, et resoumettez les messages en vol en vous appuyant sur l'idempotence pour éviter les doublons. Ne rebouclez jamais les reconnexions à chaud, cela peut faire bloquer votre IP.
Spécifications sources
Les normes publiées sur lesquelles repose cette page. S'ouvre dans un nouvel onglet.