Visão geral
SMPP é um protocolo da indústria de telecomunicações, publicado pela primeira vez pela Aldiscon/Logica no final da década de 1990 e agora mantido pelo fórum de desenvolvedores SMPP. Ele define como dois pares trocam unidades discretas chamadas PDUs (Unidades de Dados de Protocolo) numa única conexão TCP: a aplicação se conecta, envia mensagens, recebe confirmações, mantém a conexão ativa e se desconecta. Por ser binário e orientado a conexão, ele suporta cargas de trabalho estáveis de milhões de mensagens por dia com uma sobrecarga muito menor do que abrir uma solicitação HTTP por mensagem. Leia esta página do início ao fim e você entenderá todos os campos numa sessão SMPP real.
O que é SMPP e onde se encaixa
Uma sessão SMPP sempre tem duas funções. ESME (Entidade externa de mensagens curtas) é a sua aplicação — uma plataforma de SMS em massa, um serviço OTP, um sistema de alertas. O SMSC (Centro de Serviço de Mensagens Curtas), chamado de MC (Centro de Mensagens) na versão 5.0, é o operador ou agregador nó que armazena e encaminha mensagens de e para aparelhos na rede móvel. O ESME se conecta ao SMSC; o SMSC se conecta ao núcleo SS7/móvel mais amplo.
O SMPP é a espinha dorsal do A2P (Aplicação para Pessoa) mensagens — códigos de verificação, recibos, alertas, marketing — em oposição a P2P Mensagens de texto (de pessoa para pessoa) entre dois aparelhos. A2P O tráfego é de alto volume, gerado por máquinas e baseado em relatório de entrega, que é exatamente o que o SMPP foi projetado para suportar.
Porque um protocolo TCP binário em vez de HTTP? Uma única conexão SMPP é um socket de longa duração. Uma vez aberta, você evita um handshake TCP e TLS por mensagem, pode ter várias mensagens em trânsito simultaneamente (janelas assíncronas), e o SMSC envia relatórios de entrega e mensagens de entrada diretamente de volta pela mesma conexão. Com alta taxa de transferência sustentada, isso é dramaticamente mais eficiente do que uma API HTTP de solicitação/resposta — e é por isso que operadoras e grandes remetentes a padronizam.
Histórico de versões
- SMPP v3.3 — a primeira versão amplamente implantada; introduziu o conjunto principal de PDUs, mas é anterior aos TLVs (parâmetros opcionais) e à vinculação do transceptor.
- SMPP v3.4 — a versão dominante em produção atualmente. Adicionado o bind do transceptor, parâmetros TLV opcionais, message_payload e data_sm. Quase todas as integrações do mundo real que você criar usarão a versão 3.4.
- SMPP v5.0 — a versão mais recente. Renomeia SMSC para MC, adiciona PDUs de broadcast (broadcast_sm), sinalização de estado de congestionamento e TLVs mais padronizados. A adoção é limitada; suporte primeiro à v3.4 e trate a v5.0 como opcional.
Arquitetura e tipos de ligação
A topologia é simples: o ESME abre uma conexão TCP com o SMSC/MC e autentica-se com um system_id e passwordA direção em que a sessão pode transportar tráfego é definida no momento da vinculação, escolhendo uma das três opções. modos de vinculaçãoCada modo é uma PDU vinculada diferente.
Somente envio. O ESME pode enviar submit_sm, mas não pode receber deliver_sm nesta sessão. Os recibos devem chegar por meio de uma vinculação de destinatário separada.
Somente receber. O SMSC entrega deliver_sm (mensagens de entrada e DLRs) ao ESME, que não pode enviar nesta sessão.
Ambas as direções numa única sessão — submit_sm para saída, deliver_sm para entrada. Introduzido na versão 3.4 e o padrão recomendado para novas integrações.
Um quarto ator é encaminhamentoO SMSC decide, por mensagem, qual rota ou interconexão de operadora downstream uma mensagem enviada utiliza em direção ao dispositivo de destino e a qual ESME vinculada uma mensagem de entrada (originada em dispositivo móvel) pertence.
Na rede, o SMPP funciona sobre TCP. A porta padrão registada na IANA é 2775 para conexões simples. SMPPS — SMPP encapsulado em TLS — não possui uma porta padrão única; os fornecedores o expõem numa porta da sua escolha (3550, 8775 e 2776 são comuns na prática). Sempre use a porta encriptada que o seu fornecedor atribui para produção.
O ciclo de vida da sessão
Toda sessão SMPP segue o mesmo padrão: abrir TCP, vincular, manter a conexão ativa, trocar mensagens e recibos, e então desvincular e fechar. O diagrama abaixo traça uma sessão completa de transceptor — cada linha representa uma PDU, em azul fluindo do ESME para o SMSC, e em verde fluindo de volta.
Dois detalhes importantes. Primeiro, submit_sm_resp "Devolve imediatamente" significa apenas "aceito para entrega" — o resultado real chega mais tarde como um deliver_sm recibo. Em segundo lugar, cada PDU de solicitação tem um correspondente _resp que ecoa o seu sequence_number, que é como as respostas assíncronas são correlacionadas com as solicitações.
Anatomia da PDU
Tudo numa conexão SMPP é um PDUCada PDU começa com um valor fixo Cabeçalho de 16 bytes de quatro inteiros de 4 bytes (32 bits, big-endian), seguidos por um corpo específico do comando. Leia o cabeçalho primeiro e você saberá exatamente como ler o resto.
| Desvio | Campo | Tamanho | Significado |
|---|---|---|---|
| 0–3 | comprimento_do_comando | 4 bytes | Comprimento total da PDU em octetos, incluindo cabeçalho e corpo. |
| 4–7 | id_do_comando | 4 bytes | Qual operação é essa (por exemplo, submit_sm = 0x00000004). As respostas definem o bit mais significativo (0x80000000). |
| 8–11 | status_do_comando | 4 bytes | 0 nas solicitações; um código de resultado ESME_R* nas respostas (0 = ESME_ROK = sucesso). |
| 12–15 | número_de_sequência | 4 bytes | ID atribuído pelo chamador: 1…0x7FFFFFFF; o _resp correspondente o reproduz para correlacioná-los. |
| 16… | corpo | variável | Parâmetros obrigatórios para este comando, seguidos de quaisquer parâmetros TLV opcionais. |
O corpo termina com qualquer número de TLVs — parâmetros opcionais codificados como Tag (2 bytes), Comprimento (2 bytes), Valor (Comprimento bytes). Os TLVs são a forma como a v3.4 estendeu o protocolo sem quebrar versões anteriores: message_payload, receipted_message_id, campos de concatenação sar_* e muitos outros são todos usados como TLVs.
O número_de_sequência é a chave para a gestão de janelas. Como o SMPP é assíncrono, um ESME pode enviar muitos PDUs submit_sm — cada um com um número de sequência incremental — antes que qualquer resposta chegue. Quando os PDUs submit_sm_resp regressam, o seu número de sequência indica a qual submissão cada um responde. O número de PDUs não reconhecidos permitidos em trânsito é o tamanho da janela.
Referência de PDUs principais
Estas são as operações que você realmente usará. Cada solicitação tem um PDU de resposta cujo command_id é o ID da solicitação com o bit mais significativo definido (0x80000000), portanto, submit_sm 0x00000004 corresponde a submit_sm_resp 0x80000004.
| PDU | id_do_comando | Propósito |
|---|---|---|
| bind_receiver | 0x00000001 | Abra uma sessão somente para receção. |
| bind_transmitter | 0x00000002 | Abra uma sessão somente para envio. |
| bind_transceiver | 0x00000009 | Abrir uma sessão bidirecional (v3.4). |
| submit_sm | 0x00000004 | Envie uma única mensagem para um único destinatário. |
| submit_multi | 0x00000021 | Envie uma mensagem para até 254 destinos. |
| deliver_sm | 0x00000005 | SMSC → ESME : um relatório de entrega ou mensagem de entrada (MO). |
| data_sm | 0x00000103 | Alternativa bidirecional, exclusiva para TLV, submit_sm / deliver_sm. |
| query_sm | 0x00000003 | Consulte o SMSC para obter o estado atual de uma mensagem enviada. |
| cancel_sm | 0x00000008 | Cancelar uma mensagem previamente enviada e ainda não entregue. |
| replace_sm | 0x00000007 | Substitua o conteúdo/agendamento de uma mensagem pendente. |
| enquire_link | 0x00000015 | Keepalive — confirma se a sessão ainda está ativa. |
| unbind | 0x00000006 | Encerre a sessão SMPP corretamente. |
| generic_nack | 0x80000000 | Reconhecimento negativo para uma PDU não analisável/inválida. |
submit_sm campo por campo
submit_sm é a PDU que você enviará com mais frequência. O seu corpo é uma sequência de parâmetros obrigatórios e, em seguida, TLVs opcionais. Esses são os campos que importam na prática.
| Campo | O que faz |
|---|---|
| service_type | Categoria opcional de aplicação SMS (por exemplo, em branco ou um valor que o seu SMSC usa para classes de encaminhamento/faturação). |
| source_addr_ton / _npi | Tipo de número e indicador do plano de numeração para o remetente. TON 5 = alfanumérico (um ID do remetente); TON 1 = internacional E.164. |
| source_addr | O endereço do remetente — um código curto, um número longo ou um ID de remetente alfanumérico de até 11 caracteres. |
| dest_addr_ton / _npi | TON / NPI para o destino. Normalmente TON 1 (internacional), NPI 1 (ISDN / E.164). |
| destination_addr | O MSISDN do destinatário, normalmente em formato internacional sem o sinal de + inicial. |
| esm_class | Máscara de bits de modo/tipo de mensagem — por exemplo, a solicitação de um relatório de entrega é tratada por registered_delivery, enquanto o bit UDHI (0x40) diz que short_message começa com um UDH. |
| data_coding | O DCS : 0 = GSM 7 bits (padrão), 3 = Latin-1, 8 = UCS-2 (Unicode). Define o limite de caracteres. |
| registered_delivery | Defina como 1 para solicitar um comprovativo de entrega (deliver_sm) para esta mensagem; 0 para nenhum comprovativo solicitado. |
| sm_length / short_message | O comprimento da carga útil (0–254) e os próprios octetos da mensagem, codificados por data_coding. |
| message_payload (TLV 0x0424) | TLV opcional que transporta o corpo da mensagem em vez de short_message — usado para conteúdo longo com mais de 254 octetos. |
| schedule_delivery_time / validity_period | Tempo absoluto/relativo opcional para agendar a entrega e por quanto tempo o SMSC deve continuar a tentar. |
Codificação e concatenação de dados
O data_coding O campo (o Esquema de Codificação de Dados, DCS) informa ao aparelho como interpretar os bytes e decide quantos caracteres cabem num SMS.
| codificação de dados | Codificação | Solteiro | Concatenado |
|---|---|---|---|
| 0 | Alfabeto padrão 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 |
Uma mensagem com mais de um segmento é dividida e remontada no aparelho usando um UDH (Cabeçalho de Dados do Utilizador) adicionado a cada parte. O elemento de concatenação usa IEI 0x00 (8 bits referência) — um cabeçalho de 6 octetos contendo um número de referência, a contagem total de peças e o índice desta peça. Esses 6 octetos são o motivo pelo qual os limites por peça caem para 153 (GSM 7 bits) e 67 (UCS-2). Ao enviar um UDH dentro de short_message, você também deve definir o bit UDHI (0x40) em esm_class.
Existem duas maneiras de enviar conteúdo longo: construir as partes segmentadas por UDH você mesmo (cada uma um submit_sm com UDHI definido) ou entregar o corpo inteiro ao SMSC no message_payload TLV e deixe-o segmentar. Alguns SMSCs, em vez disso, aceitam os TLVs sar_msg_ref_num / sar_total_segments / sar_segment_seqnum para descrever a concatenação sem um UDH.
Relatórios de entrega (DLR)
Quando você definir registered_delivery = 1, o SMSC posteriormente informa o destino da mensagem enviando-lhe um deliver_sm com o bit de relatório de entrega definido em esm_class (0x04O texto do recibo reside no campo short_message como uma string de palavra-chave conhecida:
id:1a2b3c4d5e sub:001 dlvrd:001 submit date:2607251432 done date:2607251432 stat:DELIVRD err:000 text:Your code is 8O id corresponde ao message_id que você recebeu de volta em submit_sm_resp (também exibido no TLV receipted_message_id 0x001E). O stat O campo contém o estado final:
| estatística | Significado |
|---|---|
| DELIVRD | Entregue ao aparelho. Estado de sucesso. |
| EXPIRED | O período de validade expirou antes da entrega — o SMSC parou de tentar novamente. |
| DELETED | A mensagem foi apagada no SMSC. |
| UNDELIV | Não foi possível entregar — nenhuma rota foi encontrada ou o aparelho não pôde ser alcançado. |
| ACCEPTD | Aceito (por exemplo, lido manualmente no SMSC) — um estado intermediário. |
| UNKNOWN | O SMSC não possui informações de estado para a mensagem. |
| REJECTD | Rejeitado pelo SMSC ou por uma rede subsequente (ex.: remetente bloqueado). |
Sempre responda a um deliver_sm com um deliver_sm_resp; caso contrário, o SMSC reenviará o recibo e poderá limitar ou interromper a conexão. Observe que a formatação do recibo não é perfeitamente padronizada — os fornecedores variam ligeiramente na ordem dos campos e no mapeamento dos códigos de erro.
Códigos de erro/status do comando
Cada PDU de resposta carrega um command_status no seu cabeçalho — um ESME_R* código. Zero significa sucesso; qualquer outro valor descreve o motivo da recusa da solicitação. Esses são os que você encontrará com mais frequência.
| Código | Valor | Significado |
|---|---|---|
| ESME_ROK | 0x00000000 | Sem erros — sucesso. |
| ESME_RINVMSGLEN | 0x00000001 | Comprimento da mensagem inválido (problema sm_length e payload). |
| ESME_RINVCMDLEN | 0x00000002 | command_length inválido — o enquadramento PDU está incorreto. |
| ESME_RINVCMDID | 0x00000003 | command_id desconhecido ou não suportado. |
| ESME_RINVBNDSTS | 0x00000004 | O comando não é válido no estado de vinculação atual (por exemplo, envio numa vinculação RX). |
| ESME_RALYBND | 0x00000005 | ESME já está vinculada. |
| ESME_RINVSRCADR | 0x0000000A | Endereço de origem inválido (ID do remetente). |
| ESME_RINVDSTADR | 0x0000000B | Endereço de destino inválido. |
| ESME_RBINDFAIL | 0x0000000D | Falha na autenticação — system_id / palavra-passe incorretos. |
| ESME_RINVPASWD | 0x0000000E | Palavra-passe inválida. |
| ESME_RTHROTTLED | 0x00000058 | Erro de limitação de taxa — você excedeu a taxa de mensagens permitida. |
| ESME_RSUBMITFAIL | 0x00000045 | Falha no submit_sm / submit_multi. |
| ESME_RSYSERR | 0x00000008 | Erro no sistema SMSC. |
O registo completo — incluindo intervalos de fornecedores específicos do fornecedor — pode ser pesquisado no Referência de códigos de erro SMPP.
Taxa de transferência, janelas e limitação de velocidade
A taxa de transferência em SMPP é medida em TPS — transações (submit_sm) por segundo — e é regido por dois fatores: a taxa permitida pelo SMSC e quantas mensagens você mantém em trânsito. Como o SMPP é assíncrono, você não precisa esperar por cada submit_sm_resp antes de enviar o próximo PDU. O número de envios não confirmados que você permite simultaneamente é o seu tamanho da janela (geralmente de 10 a 100). Uma janela maior oculta a latência de ida e volta e aumenta o TPS efetivo — até o limite máximo do SMSC.
- Respeite o acelerador. Quando o SMSC devolver ESME_RTHROTTLED (0x58), recue — faça uma pausa e tente novamente com recuo exponencial em vez de insistir na conexão vinculada, o que pode causar a desconexão.
- Mantenha a atividade num ritmo constante. Envie enquire_link aproximadamente a cada 30 segundos enquanto estiver ocioso; se algumas mensagens não forem respondidas, assuma que o link está inativo.
- Reconecte-se de forma consciente. Ao desconectar, reconecte e reassocie com backoff e jitter; não faça loops curtos. Monitorize os números de sequência pendentes para que você possa conciliar os recibos após uma reconexão.
- Escala com amarras, com cuidado. Um TPS agregado mais alto geralmente resulta de múltiplas conexões — mas apenas até o limite autorizado pelo seu fornecedor por conta.
Exemplo de código
Um exemplo ilustrativo do fluxo conectar → vincular → enviar em pseudocódigo no estilo Node.js. Bibliotecas SMPP reais (por exemplo, node-smpp, jSMPP para Java ou python-smpplib) lidam com a codificação de PDUs para você; isto mostra o formato da sessão, não a API de uma 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
A BroadNet opera um gateway SMSC de nível de operadora que aceita conexões SMPP v3.4 sobre TLS. Você obtém conexões de transceptor, alto TPS com janelas assíncronas, relatórios de entrega completos, Unicode e concatenação, e uma conexão com lista de permissões de IP e credenciais para alcançar operadoras em todo o mundo. É o mesmo protocolo ensinado nesta página — direcionado para rotas reais.
Solicite uma vinculação para a sua conta e a nossa equipa de engenharia de vendas aprovisionará seu system_id, endpoint TLS, TPS e lista de permissões de IP. Ou leia como o gateway é construído.
Perguntas frequentes
Qual porta o SMPP utiliza?
A porta TCP 2775, registada pela IANA, é a padrão para SMPP simples. Não existe uma única porta TLS padrão — o SMPP (SMPP sobre TLS) geralmente utiliza uma porta específica do fornecedor, como 3550, 8775 ou 2776; portanto, utilize sempre a porta atribuída pelo seu operador de SMSC. A BroadNet publica o host de vinculação, a porta simples e a porta TLS juntamente com as suas credenciais.
Qual a diferença entre submit_sm e data_sm?
O submit_sm é o PDU principal que um ESME usa para enviar uma única mensagem curta; ele carrega o campo short_message clássico (até 254 octetos) mais TLVs opcionais. O data_sm é uma alternativa simplificada e simétrica introduzida no SMPP v3.4 que sempre carrega o conteúdo do TLV message_payload e pode fluir em qualquer direção (ESME→SMSC ou SMSC→ESME). A maior parte do tráfego A2P usa submit_sm; o data_sm é usado quando o seu formato bidirecional, composto apenas por TLVs, é preferido.
Como o SMPP lida com Unicode?
O Unicode é enviado definindo data_coding como 8 (UCS-2 / UTF-16BE big-endian). Um único segmento UCS-2 contém 70 caracteres; segmentos UCS-2 concatenados contêm 67 caracteres cada, pois 6 octetos são consumidos pelo cabeçalho de concatenação UDH. GSM de 7 bits (data_coding 0) é o padrão para texto latino básico com 160/153 caracteres.
O que é um bind de transceptor?
Um bind de transceptor (TRX) é uma única sessão SMPP, aberta com bind_transceiver, que pode tanto enviar mensagens (submit_sm) quanto receber mensagens e relatórios de entrega (deliver_sm) pela mesma conexão TCP. Ele substitui o padrão antigo de abrir binds de transmissor e recetor separados, e é o modo recomendado para a maioria das integrações modernas.
Porque usar SMPP em vez de uma API HTTP?
SMPP é um protocolo TCP binário persistente, projetado para alta taxa de transferência sustentada. Uma vinculação de longa duração evita handshakes TLS/TCP por mensagem, suporta janelas assíncronas (várias solicitações submit_sm pendentes antes de um ack) e entrega recibos deliver_sm em tempo real e mensagens originadas em dispositivos móveis de volta pelo mesmo socket. Para volumes A2P muito altos e estáveis, é mais eficiente do que o HTTP de requisição/resposta; o HTTP REST é mais simples para volumes menores e canais mais complexos.
O que é enquire_link?
O enquire_link é um PDU de keepalive leve que um dos pares envia para confirmar se a sessão SMPP e a conexão TCP subjacente ainda estão ativas; o outro lado responde com enquire_link_resp. Normalmente, é enviado a cada 30 segundos durante períodos de inatividade. Se vários enquire_links não forem respondidos, o par considera a conexão como inativa e se reconecta.
O que significa command_length no cabeçalho de uma PDU?
O campo `command_length` é o primeiro campo de 4 bytes de cada cabeçalho de PDU SMPP e contém o comprimento total de toda a PDU em octetos, incluindo o próprio cabeçalho de 16 bytes e todo o corpo. Um recetor lê esses 4 bytes primeiro para saber exatamente quantos bytes mais ler para obter a PDU completa antes de analisar `command_id`, `command_status` e `sequence_number`.
O que é um comprovativo de entrega (DLR) no SMPP?
Um relatório de entrega é o SMSC que informa ao ESME o destino final de uma mensagem enviada. Ele chega como um PDU deliver_sm com o bit de relatório de entrega da classe esm definido (0x04). A mensagem curta contém uma string de recibo com palavras-chave — id, sub, dlvrd, data de envio, data de conclusão, stat e err — onde stat carrega o estado final, como ENTREGUE, EXPIRADO, NÃO ENTREGUE ou REJEITADO.