收发超长短信的资料汇编

摘要:
因为我想发送和解析长信和短信,我已经沉浸在互联网中很长一段时间,终于解决了我的疑虑,所以我记录了我认为有用的信息。B: SMS中心号码类型,两个十六进制数字。

因为要发送和解析长短信,在网上浸淫许久,终于解惑,因此记录下我认为有用的资料。

一、所谓超长短信就是:当短信内容超过70个汉字或140个字符,发送的时候需要分成多条,但是用户手机接收时候是一条。

二、在说长短信之前必须先熟悉一下PDU的格式说明:

一般的PDU编码由A B C D E F G H I J K L M十三项组成。
    A:短信息中心地址长度,2位十六进制数(1字节)。
    B:短信息中心号码类型,2位十六进制数。
    C:短信息中心号码,B+C的长度将由A中的数据决定。
    D:文件头字节,2位十六进制数。
    E:信息类型,2位十六进制数。
    F:被叫号码长度,2位十六进制数。
    G:被叫号码类型,2位十六进制数,取值同B。
    H:被叫号码,长度由F中的数据决定。
    I:协议标识,2位十六进制数。
    J:数据编码方案,2位十六进制数。
    K:有效期,2位十六进制数。
    L:用户数据长度,2位十六进制数。
    M:用户数据,其长度由L中的数据决定。J中设定采用UCS2编码,这里是中英文的Unicode字符。

PDU编码协议简单说明:

例1 发送:SMSC号码是+8613800250500,对方号码是13693092030,消息内容是“Hello!”。从手机发出的PDU串可以是
    08 91 68 31 08 20 05 05 F0 11 00 0D 91 68 31 96 03 29 30 F0 00 00 00 06 C8 32 9B FD 0E 01
    对照规范,具体分析:
    分段 含义 说明
    08 SMSC地址信息的长度 共8个八位字节(包括91)
    91 SMSC地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
    68 31 08 20 05 05 F0 SMSC地址 8613800250500,补‘F’凑成偶数个
    11 基本参数(TP-MTI/VFP) 发送,TP-VP用相对格式
    00 消息基准值(TP-MR) 0
    0D 目标地址数字个数 共13个十进制数(不包括91和‘F’)
    91 目标地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
    68 31 96 03 29 30 F0 目标地址(TP-DA) 8613693092030,补‘F’凑成偶数个
    00 协议标识(TP-PID) 是普通GSM类型,点到点方式
    00 用户信息编码方式(TP-DCS) 7-bit编码
    00 有效期(TP-VP) 5分钟
    06 用户信息长度(TP-UDL) 实际长度6个字节
    C8 32 9B FD 0E 01 用户信息(TP-UD) “Hello!”


    例2:例2 接收:SMSC号码是+8613800250500,对方号码是13693092030,消息内容是“你好!”。手机接收到的PDU串可以是
    08 91 68 31 08 20 05 05 F0 84 0D 91 68 31 96 03 29 30 F0 00 08 30 30 21 80 63 54 80 06 4F 60 59 7D 00 21
    对照规范,具体分析:
    分段 含义 说明
    08 地址信息的长度 个八位字节(包括91)
    91 SMSC地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
    68 31 08 20 05 05 F0 SMSC地址 8613800250500,补‘F’凑成偶数个
    84 基本参数(TP-MTI/MMS/RP) 接收,无更多消息,有回复地址
    0D 回复地址数字个数 共13个十进制数(不包括91和‘F’)
    91 回复地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
    68 31 96 03 29 30 F0 回复地址(TP-RA) 8613693092030,补‘F’凑成偶数个
    00 协议标识(TP-PID) 是普通GSM类型,点到点方式
    08 用户信息编码方式(TP-DCS) UCS2编码
    30 30 21 80 63 54 80 时间戳(TP-SCTS) 2003-3-12 08:36:45  +8时区
    06 用户信息长度(TP-UDL) 实际长度6个字节
    4F 60 59 7D 00 21 用户信息(TP-UD) “你好!”

没错,长短信的关键之一就在于pdu的D项目(也就是”文件头字节“/TP-MTI)的取值。这个数值的获得是通过二进制数获得的,例如

例子一中的11转为二进制是0001 0001,例子二中的84转为二进制是1000 0100

其实二进制中的每一位都有自己的意义,我们来具体看看(这里说明时定义左边为第一位):

      第一位:应答路径—TP-RP(TP-Reply-Path):0—不设置; 1—设置

  第二位:用户数据头标识—TP-UDHI(TP-User-Data-Header-Indicator):0—不含任何头信息; 1—含头信息(本短信是没有头信息的,下文中会有包含头信息的短信,到时再具体解析头信息UDH)

  第三位:状态报告要求—TP-SPR(TP-Status-Report-Request):0—需要报告; 1—不需要报告

  第四、五位:有效期格式—TP-VPF(TP-Validity-Period-Format):00—不提供(Not present); 10—整型(标准);01—预留; 11—提供8位字节的一半(Semi-Octet Represented)

  第六位:拒绝复制—TP-RD(TP-Reject-Duplicates):0—接受复制; 1—拒绝复制

  第七、八位:信息类型提示—TP-MTI(TP-Message-Type-Indicator):00—接收(Deliver); 01—发送(Submit)

TP_udhi :0代表内容体里不含有协议头信息 1代表内容含有协议头信息(长短信的协议头,也就是说把基本参数(TP-MTI/VFP)值设置成0X51)

当设置内 容体包含协议头后,你就可以在用户数据部分的前面加上协议头了

三、长短信的协议头:

长短信协议头有两种】:

(一)、6位协议头格式:05 00 03 XX MM NN
                     byte 1 : 05, 表示剩余协议头的长度
                     byte 2 : 00, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为1(格式中的X值)。
                     byte 3 : 03, 这个值表示剩下短信标识的长度
                     byte 4 : XX,这批短信的唯一标志(被拆分的多条短信,此值必需一致),事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯一并不是很 重要。
                     byte 5 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。
                     byte 6 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。
                     例如:05 00 03 39 02 01

包头一共6个字节,如下:
1、字节一:包头长度,固定填写0x05;
2、字节二:包头类型标识,固定填写0x00,表示长短信;
3、字节三:子包长度,固定填写0x03,表示后面三个字节的长度;
4、字节四到字节六:包内容:
  1)字节四:长消息参考号,每个SP给每个用户发送的每条参考号都应该不同,可以从0开始,每次加1,最大255,便于同一个终端对同一个SP的消息的不同的长短信进行识别;
  2)字节五:本条长消息的的总消息数,从1到255,一般取值应该大于2;
  3)字节六:本条消息在长消息中的位置或序号,从1到255,第一条为1,第二条为2,最后一条等于字节五的值。
              

(二)、7位的协议头格式:06 08 04 XX XX MM NN
                     byte 1 : 06, 表示剩余协议头的长度
                     byte 2 : 08, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为2(格式中的XX值)。
                     byte 3 : 04, 这个值表示剩下短信标识的长度
                     byte 4-5 : XX XX,这批短信的唯一标志,事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯一并不是很重要。
                     byte 6 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。
                     byte 7 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。
                     例如:06 08 04 00 39 02 01       

你可以任选一种协议头,但是要注意的是:协议里短信标志这个字段在一条长短信中必须要一样,不然手机会解析成三条, 并三条都 是错误短信。 

还有就是,加了协议头之后,用户数据部分的长度也要相应的减少,例如采用6字节的协议头,则把短信内容按134字节来分割,在头部添加6字节udhi,刚好 140字节。

四、总结:

  至此,总结超长短息的关键地方:

1、是超长短信,pdu的D项目要设置为51,否则11

2、用户数据拆分长度要去掉用户协议头的长度,我用6位的协议头,所以按照134的最大长度(67个汉字或字符)来拆分信息。

3、协议头的短信ID,在一条长短息拆分成的短信中应该保持一致,不同长短息的ID应该不同。另外,这里的ID和总数以及索引数字都要格式化为16进制

4、拆分后的信息作为单独的短信发送即可,接收方的手机(多数)会自动拼接成一条长短信。

5、自己解析长短息首先要根据PDU头信息的D项看看左边第二位是否为1,然后根据两种协议的前三位来判断具体是那种协议头。解析数据应该去掉协议头的几个字节。

免责声明:文章转载自《收发超长短信的资料汇编》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[转载]Latex文件转成pdf后的字体嵌入问题的解决Hutool-解析JSON下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[转]HEX文件格式

Intel HEX 文件是由一行行符合Intel HEX 文件格式的文本所 构 成的ASCII 文本文件。在Intel HEX 文件中,每一行包含一 个 HEX 记录 。 这 些 记录 由 对应 机器 语 言 码 和/ 或常量 数 据的十六 进 制 编码数 字 组 成。Intel HEX 文件通常用于 传输将 被存于ROM 或者EPROM 中的程序和 数 ...

gdb查看内存(转)

可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语 法如下所示:x/<n/f/u> <addr>n、f、u是可选的参数。 n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个 内存单元的内容,一个内存单元的大小由后面的u定义。 f 表示显示的格式,参见下面。如果地址所指的是字符串,那么格式...

调用webservice接口,报错:(十六进制值0x01)是无效的字符

#事故现场 调用webservice接口,报错:(十六进制值0x01)是无效的字符。如图:意思是webservice返回的信息中包含无效的字符,无法解析成xml; #分析 使用postman向webservice发送请求,请求成功,返回了数据,但在数据中发现了一些莫名其妙的字符,如图:因数据来源数据库,故去数据库中查询,果然又发现,如图:将异常文本复制到...

GDB下查看内存命令(x命令)

http://blog.csdn.net/allenlinrui/article/details/5964046 可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示: x/<n/f/u> <addr> n、f、u是可选的参数。 n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个...

C语言中的正负数及其输出

在数学中,数字有正负之分。在C语言中也是一样,short、int、long 都可以带上正负号,例如: //负数 short a1 = -10; short a2 = -0x2dc9; //十六进制 //正数 int b1 = +10; int b2 = +0174; //八进制 int b3 = 22910; //负数和正数相加 lon...

JAVA实现二进制,十六进制输出

public class Main { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(Integer.toBinaryString(320*1024)); System....