Java pdu短信解码全面解析

yizhihongxing

Java pdu短信解码全面解析

短信协议数据单元(PDU)简介

短信协议数据单元(Protocol Data Unit,PDU)是一种短消息传送协议,它将SMS消息内容进行编码和封装,以方便在移动电话网络上进行传输和接收。在Java中,我们可以使用PDU来解码和编码短信。

短信编码

短信可由两部分组成:短信消息中心号码(SMSC Address)和短信内容(Message)。在将短信进行编码之前,需要将短信消息中心号码和短信文本转换成PDU格式。

短信消息中心号码的PDU编码

短信消息中心号码采用地址格式,它由两个字段组成:地址长度(Address Length)和地址信息(Address Information)。其中,地址长度是一个字节,地址信息则是地址号码。地址信息还包括地址类型,包括国际格式,国内格式和其它格式。

以下示例是以中国移动为例,将+8613800138000转换成PDU格式的过程,需要将+86替换成0x91,然后将每两位数字进行交换,最终得到:0x9183C0013800F0。

public static String encodeSmscAddress(String address) {
    int length = (address.length() - (address.startsWith("+") ? 1 : 0)) / 2;
    byte[] pdu = new byte[length + 1];
    pdu[0] = (byte) length;
    for (int i = 0, j = 1; i < length; i++, j += 2) {
        pdu[j] = (byte) Integer.parseInt(address.substring(j - 1, j + 1), 16);
    }
    if (address.startsWith("+")) {
        pdu[1] = (byte) 0x91;
    }
    return HexUtils.bytesToHexString(pdu);
}

短信内容的PDU编码

短信内容的PDU编码需要进行如下处理:

  • 对短信文本进行编码,采用7位压缩方式或16位Unicode编码(大多数情况下使用7位压缩方式)。
  • 计算消息协议数据单元头部长度并将其转换为16进制字符串。
  • 将消息协议数据单元头部和消息文本通过空格分开。

以下示例是将一段文本“I love Java”转换成PDU格式的过程。

public static String encodeMessage(String message) {
    int length = message.length();
    byte[] data;
    int udhLength = 0;
    if (length > 160) {
        udhLength = 6;
        int n = (length + 132 - 1) / 132;
        byte[] udhData = new byte[udhLength + 1];
        udhData[0] = (byte) udhLength;
        udhData[1] = (byte) 0x08;
        udhData[2] = (byte) 0x04;
        udhData[3] = (byte) ((n >> 8) & 0xff);
        udhData[4] = (byte) (n & 0xff);
        udhData[5] = (byte) 0x01;
        data = new byte[length + udhLength];
        System.arraycopy(udhData, 0, data, 0, udhLength);
        System.arraycopy(message.getBytes(), 0, data, udhLength, length);
        length += 7;
    } else {
        data = message.getBytes();
    }
    StringBuilder sb = new StringBuilder();
    sb.append(Integer.toHexString(length)).append(":");
    sb.append("00").append(":");
    sb.append("00").append(":");
    sb.append("00").append(":");
    sb.append(Integer.toHexString(udhLength)).append(":");
    sb.append(HexUtils.bytesToHexString(data));
    return sb.toString().toUpperCase();
}

短信解码

短信解码主要是将PDU格式的数据解析成短信消息中心号码和短信内容。

短信消息中心号码的PDU解码

短信消息中心号码的PDU解码需要根据地址类型进行不同的处理,以中国移动为例,地址类型为0x91,其它地址类型根据具体情况而定,采用相应的处理方式解码即可。

public static String decodeSmscAddress(String pdu) {
    byte[] bytes = HexUtils.hexStringToBytes(pdu);
    int length = bytes[0] & 0xff;
    StringBuilder sb = new StringBuilder();
    byte digit;
    for (int i = 1; i <= length; i++) {
        digit = bytes[i];
        if ((i == 1) && ((digit & 0xff) == 0x91)) {
            sb.append("+");
        }
        sb.append(String.format("%02X", digit));
        if ((i == length) && ((digit & 0x0F) == 0x0F)) {
            sb.deleteCharAt(sb.length() - 1);
        }
    }
    return sb.toString();
}

短信内容的PDU解码

短信内容的PDU解码需要从PDU字符串中分离出消息协议数据单元头部和消息文本,然后对消息文本进行反编码。

public static String decodeMessage(String pdu) {
    byte[] bytes = HexUtils.hexStringToBytes(pdu);
    int udhLength = bytes[4] & 0xff;
    byte[] data = new byte[bytes.length - 7 - udhLength];
    System.arraycopy(bytes, 7 + udhLength, data, 0, data.length);
    int length = Integer.parseInt(pdu.substring(0, 2), 16);
    String hexText = HexUtils.bytesToHexString(data);
    if ((bytes[6] & 0x03) == 0x03) {
        hexText = hexText.substring(0, hexText.length() - 2);
        length--;
    }
    return extractText(hexText, length);
}

该方法中引用的方法extractText() 可以通过以下方式获得:

private static String extractText(String hexText, int length) {
    StringBuilder sb = new StringBuilder();
    int index = 0;
    while (index < hexText.length()) {
        int end = Math.min(index + 2, hexText.length());
        int i = Integer.parseInt(hexText.substring(index, end), 16);
        if ((i & 0x80) == 0x80) {
            end = Math.min(index + 4, hexText.length());
            int j = Integer.parseInt(hexText.substring(index, end), 16);
            sb.append(String.valueOf((char) ((j & 0x7F) << 8 | (i & 0x7F))));
            index += 4;
        } else {
            sb.append(String.valueOf((char) i));
            index += 2;
        }
    }
    return sb.toString().substring(0, length);
}

示例

假设我们有这样一条短信,文本为“Hello, world!”,短信消息中心号为+8613800138000。

编码

对短信消息中心号码和短信内容进行编码。

String smscAddress = "+8613800138000";
String message = "Hello, world!";
String pdu1 = encodeSmscAddress(smscAddress);
String pdu2 = encodeMessage(message);

输出结果:

pdu1: 91938310038000F0
pdu2: 0C8BBA9380000AB0040B4AE06B95E06

解码

对PDU字符串进行解码。

String pdu1 = "91938310038000F0";
String pdu2 = "0C8BBA9380000AB0040B4AE06B95E06";
String smscAddress = decodeSmscAddress(pdu1);
String message = decodeMessage(pdu2);

输出结果:

smscAddress: +8613800138000
message: Hello, world!

以上就是Java pdu短信解码的全面攻略,希望能对您有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java pdu短信解码全面解析 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • java servlet结合mysql搭建java web开发环境

    概述 在Java Web开发中,结合MySQL数据库使用Java Servlet技术是非常常见的一种方式。本文将给出完整的攻略,演示如何在本地环境下搭建Java Servlet和MySQL结合使用的开发环境,并提供两个示例进行说明。 环境准备 在开始之前需要安装以下组件: JDK Tomcat MySQL 配置Tomcat 下载Tomcat并解压到本地目录(…

    Java 2023年6月16日
    00
  • Java调用Shell命令和脚本的实现

    Java调用Shell命令和脚本是一种常见的技术,可以为开发人员带来更灵活的开发方式。在这里,我们将详细讲解Java调用Shell命令和脚本的实现攻略。 什么是Shell命令和脚本 Shell命令和脚本都是运行在Linux/Unix系统上的脚本语言。Shell命令是一种命令行工具,用于在终端中实现系统管理任务。Shell脚本是一种执行自动化任务的脚本文件,可…

    Java 2023年5月26日
    00
  • jsp web.xml文件的作用及基本配置

    下面是详细讲解“jsp web.xml文件的作用及基本配置”的完整攻略。 一、web.xml文件的作用 web.xml是Java Web应用程序的核心配置文件之一,主要作用是为Java Web应用程序提供全局配置及部署信息。其内容以XML格式存储,主要包含了应用程序的基本信息、Servlet配置信息、Filter配置信息、Listener配置信息等。 web…

    Java 2023年6月15日
    00
  • 详解springmvc常用5种注解

    让我们来详解一下SpringMVC常用的5种注解。 1. @RequestMapping @RequestMapping注解可以定义控制器方法的URL值。 一个控制器可以有多个方法,并且它们都可以映射到不同的URL值。 示例代码: @Controller @RequestMapping("/users") public class Use…

    Java 2023年6月15日
    00
  • java解一个比较特殊的数组合并题

    我将为您讲解如何解决一个比较特殊的Java数组合并题。我将分为以下步骤进行讲解: 确定题目要求:根据题目要求,我们需要实现一个方法,用于将两个有序数组合并为一个大的有序数组。 确定解题思路:我们可以使用双指针的方式来解决这个问题,具体思路如下: 1) 我们定义三个指针:p1指向第一个数组的开头,p2指向第二个数组的开头,p3指向新数组的开头。 2) 比较p1…

    Java 2023年5月26日
    00
  • Java如何判断整数溢出,溢出后怎么得到提示

    Java中整数类型(int, long等)变量的范围是有限的,当一个变量的数值超出了它的范围时,就会发生整数溢出。溢出的结果与数值运算的结果不同,可能导致程序运行异常,所以我们需要在程序中判断整数是否溢出,并得到提示以确保程序的正确性。 判断整数溢出的方法是通过与最值的比较来实现的。以int类型的整数为例,最大值为2^31-1(即2147483647),最小…

    Java 2023年5月25日
    00
  • Java8 如何正确高效的使用并行流

    Java8 如何正确高效的使用并行流 什么是并行流 在 Java8 中,我们可以使用 Stream API 提供的 parallel() 方法来创建并行流,将一个大任务划分成多个小任务并行执行。 如何使用并行流 小心使用 并行流虽然可以大大提高执行效率,但是在使用时需要小心,因为它并不是万能的,有时候反而会降低效率。以下是一些使用并行流时需要注意的点: 并行…

    Java 2023年5月18日
    00
  • XSS测试语句大全

    首先,需要了解XSS攻击的定义和常见形式,XSS攻击是一种Web应用程序漏洞攻击,攻击者将恶意的脚本代码注入到Web页面中。常见的XSS攻击形式包括反射型XSS、存储型XSS和DOM型XSS等。 接着,根据不同的XSS攻击类型选择合适的测试语句。以下是一些常用的测试语句: 基本测试语句: <script>alert(‘XSS’)</scri…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部