活动介绍
file-type

Java实现SMPP协议的jSMPP库详细介绍

ZIP文件

1星 | 下载需积分: 50 | 468KB | 更新于2025-08-13 | 160 浏览量 | 14 下载量 举报 收藏
download 立即下载
从给定的文件信息中,我们可以提取以下知识点: 1. **什么是jSMPP**: jSMPP是SMPP(Short Message Peer to Peer)协议的Java语言实现。SMPP是一种开放的数据通信协议,用于在短消息服务中心(SMSC)和外部短消息实体(ESME)之间进行通信。通过使用jSMPP,开发者能够编写Java程序,以便能够与SMSC进行交互,实现短信的发送和接收。 2. **jSMPP的功能特点**: - 支持SMPP协议的3.4和5.0版本。 - 提供了一个Java接口,便于Java开发者用来与消息中心通信。 - 高性能,能够处理高流量,据描述能够达到每秒3000到5000条消息的处理能力。 - jSMPP不是高级库,意味着它可能需要开发者具备更多底层通信协议的理解和实现能力。 3. **jSMPP的适用人群**: 对于那些需要快速实现SMPP协议通信,但缺乏深入底层细节时间或经验的开发者,项目文档中建议使用高级库或抽象层,例如Apache Camel SMPP组件,以简化开发流程。 4. **项目的历史和维护情况**: jSMPP项目的起源可以追溯到Google Code,而在2013年前由uudashr维护。目前,该项目已经成为一个社区维护的项目,这意味着它具有活跃的贡献者基础和持续的更新。 5. **如何构建和部署jSMPP**: 文档中提供了一条Maven命令(`mvn deploy -DperformRelease=true -Durl= -DrepositoryId=sonatype-nexus-staging -Dgpg.passphrase=<您的密码>`),用于部署jSMPP到仓库。这一过程可能需要项目维护者或具有相应权限的用户操作,需要登录到指定的仓库,并在“登台存储库”链接中完成部署的各个环节,包括选择正确的存储库和关闭操作。 6. **jSMPP的使用场景**: jSMPP适用于需要通过Java实现短信服务集成的场景,例如: - 企业级短信营销和通知平台。 - 在线服务提供商,用以发送验证码、交易通知等。 - 移动应用开发者集成短信服务到应用中。 7. **与其它技术栈的比较**: 与jSMPP相比,使用如Apache Camel等高级库可能更加快速和简便,因为这些库抽象了底层通信细节,提供了更加简洁和易于理解的API。然而,对于需要精细控制或者特别定制的SMPP实现,jSMPP提供了一个强大的工具集,允许开发者根据SMPP协议详细规定实现各种自定义功能。 8. **安全性和密码保护**: 在进行部署操作时,命令行中提及了需要使用密码(`-Dgpg.passphrase=<您的密码>`),这表明jSMPP项目可能采用了某种形式的加密措施,以确保部署过程的安全性。这通常涉及到数字签名或加密认证等机制,用于保证代码发布的完整性。 9. **维护者的建议**: 维护者明确指出,jSMPP不适用于快速入门的开发者,这或许是因为它更偏向底层操作,需要开发者具有通信协议和网络编程方面的知识。对于这部分开发者,维护者推荐使用更高级别的抽象层或库来实现SMPP功能。 通过以上知识点的整理,我们可以看出jSMPP是一个功能强大且专业的Java库,它允许开发者用Java语言与短信服务进行交互,尽管它要求开发者对网络编程和SMPP协议有一定程度的理解。

相关推荐

filetype

package org.yqq.server.smpp; import org.jsmpp.session.SMPPServerSession; import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Component public class SmppServer implements Runnable { // @Value("${smpp.server.port:2775}") private int port = 7788; // @Value("${smpp.server.systemid:systemid}") private String systemId = "systemid"; // @Value("${smpp.server.password:password}") private String password = "123"; private final ExecutorService executor = Executors.newCachedThreadPool(); private ServerSocket serverSocket; private volatile boolean running = true; // 跟踪活动会话 private final ConcurrentHashMap<SMPPServerSession, Boolean> activeSessions = new ConcurrentHashMap<>(); @Override public void run() { try { serverSocket = new ServerSocket(port); System.out.println("SMPP Server started on port " + port); //优雅关闭 serverSocket.setSoTimeout(1000); while (running) { Socket socket = serverSocket.accept(); System.out.println("New client connected: " + socket.getInetAddress()); executor.execute(new SessionHandler(socket,activeSessions)); } } catch (IOException e) { if (running) { System.err.println("Server error: " + e.getMessage()); } } } @PreDestroy public void stop() { running = false; // 关闭所有活动会话 activeSessions.keySet().forEach(session -> { try { if (session.getSessionState().isBound()) { session.unbind(); } session.close(); } catch (Exception e) { System.err.println("Error closing session: " + e.getMessage()); } }); executor.shutdown(); if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { System.err.println("Error closing server socket: " + e.getMessage()); } } System.out.println("SMPP Server stopped"); } } 执行run方法会报错 具体的这一行 Socket socket = serverSocket.accept(); 然后进入了catch 执行了 System.err.println("Server error: " + e.getMessage()); 控制台输出Server error: Accept timed out

filetype

我现在在使用 jsmpp 3.0.1 开发短信客户端 发送长短信 下面是我的代码package org.yqq.client; import org.jsmpp.bean.*; import org.jsmpp.session.SMPPSession; import org.jsmpp.session.SubmitSmResult; import org.jsmpp.util.DeliveryReceiptState; import org.jsmpp.util.MessageId; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Random; public class LongMessageSender { // 生成随机参考号 (0-255) private static byte generateReferenceNumber() { return (byte) new Random().nextInt(256); } // 根据编码计算最大消息长度 private static int getMaxSegmentLength(Alphabet alphabet) { switch (alphabet) { case ALPHA_DEFAULT: // GSM 7-bit return 153; // 160 - 7 (UDH占用) case ALPHA_8_BIT: // 8-bit return 134; // 140 - 6 (UDH占用) case ALPHA_UCS2: // UCS2 return 67; // 70 - 3 (UDH占用) default: return 134; } } // 分割长消息 private static List<byte[]> splitMessage(String message, Alphabet alphabet) { Charset charset; switch (alphabet) { case ALPHA_DEFAULT: charset = StandardCharsets.US_ASCII; break; case ALPHA_UCS2: charset = StandardCharsets.UTF_16BE; break; default: charset = StandardCharsets.ISO_8859_1; } byte[] messageBytes = message.getBytes(charset); int maxSegmentLength = getMaxSegmentLength(alphabet); List<byte[]> segments = new ArrayList<>(); int totalSegments = (int) Math.ceil((double) messageBytes.length / maxSegmentLength); // 如果消息很短,不需要分割 if (totalSegments <= 1) { segments.add(messageBytes); return segments; } for (int i = 0; i < totalSegments; i++) { int start = i * maxSegmentLength; int end = Math.min(start + maxSegmentLength, messageBytes.length); int segmentLength = end - start; // 创建带UDH的片段 byte[] segmentWithUdh = new byte[segmentLength + 6]; // UDH结构 (6字节): // [0]: UDH长度 (5) // [1]: 信息元素标识 (0x00 = 连接消息) // [2]: 信息元素数据长度 (3) // [3]: 参考号 (同一消息所有片段相同) // [4]: 总片段数 // [5]: 当前片段序号 (1-based) segmentWithUdh[0] = 0x06; // UDH长度 segmentWithUdh[1] = 0x08; // 连接消息标识 segmentWithUdh[2] = 0x04; // 信息元素数据长度 segmentWithUdh[3] = generateReferenceNumber(); // 参考号 segmentWithUdh[4] = (byte) totalSegments; // 总片段数 segmentWithUdh[5] = (byte) (i + 1); // 当前片段序号 // 复制消息内容 System.arraycopy(messageBytes, start, segmentWithUdh, 6, segmentLength); segments.add(segmentWithUdh); } return segments; } // 发送长消息 public static List<MessageId> sendLongMessage( SMPPSession session, String source, String destination, String message, Alphabet alphabet ) throws Exception { List<byte[]> segments = splitMessage(message, alphabet); List<MessageId> messageIds = new ArrayList<>(); // 设置ESMClass包含UDHI标志 (0x40) ESMClass esmClass = new ESMClass(); esmClass.setUdhi(true); // 设置UDHI标志位 GeneralDataCoding dataCoding = new GeneralDataCoding(alphabet); for (byte[] segment : segments) { SubmitSmResult result = session.submitShortMessage( "CMT", TypeOfNumber.INTERNATIONAL, NumberingPlanIndicator.ISDN, source, TypeOfNumber.INTERNATIONAL, NumberingPlanIndicator.ISDN, destination, esmClass, (byte) 0, // protocolId (byte) 1, // priorityFlag null, // scheduleDeliveryTime null, // validityPeriod new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE), (byte) 0, // replaceIfPresentFlag dataCoding, (byte) 0, // default message ID segment // 消息内容 (包含UDH) ); messageIds.add(result.getMessageId()); } return messageIds; } // 使用示例 public static void main(String[] args) { try { SMPPSession session = new SMPPSession(); // 配置并连接会话... String longMessage = "这是一条非常长的消息,需要被分割成多个部分发送..." + "因为它超过了SMPP协议允许的单条消息最大长度限制..." + "我们将使用UDH(用户数据头)来标识这些片段属于同一个长消息..."; List<MessageId> messageIds = sendLongMessage( session, "123456", "987654", longMessage, Alphabet.ALPHA_UCS2 ); System.out.println("长消息已发送,包含 " + messageIds.size() + " 个片段"); } catch (Exception e) { e.printStackTrace(); } } } esmClass.setUdhi(true); // 设置UDHI标志位 没有 setUdhi(true); 这个方法

王萌昊
  • 粉丝: 34
上传资源 快速赚钱