1.1. 基本知识
短信开发指通过串口 at 命令驱动短信猫进行短信发送和接收操作。
在 java 中 主要使用 javax.comm 包进行开发,
sun 公司网上地址 : http://java.sun.com/products/javacomm/
使用工具 : windows 自带超级终端
短信猫操作分为三种模式: block,pdu 和 Text
短信传送有三种编码: 7 位, 8 位, UniCode
at 命令 ,at 命令是驱动短信设备的标准工业命令,除了业界的标准之外,每个厂商可能会对其进行扩展,不过一般来说,标准命令应该够用,这次用的是西门子 tc35i ,有专门的 at 命令文档。
1.1.1. 相关文档
Gsm03.38 规范: Alphabets and language-specific information 着重介绍短信发送中对字符集的控制部分
Gsm03.40 规范: Technical realization of the Short Message Service (SMS) Point-to-Point (PP) 详细介绍各种不同短信的不同实现
Gsm07.05 规范: Use of Data Terminal Equipment - Data Circuit terminating;Equipment (DTE - DCE) interface for Short Message Service (SMS) and Cell Broadcast Service (CBS) ,介绍 at 的一些控制命令。
Gsm07.07 规范:着重介绍 at 的短信相关命令,可以说是 at 的 sms 规范。
1.1.2. Block 模式
Block 模式基本已经被 pdu 模式取代,没有具体研究
1.1.3. Text 模式
Text 模式比较简单,但是支持的设备不是很全,而且对于中文似乎有些问题,在金笛的网站技术资料中似乎提到了一句不能实现中文。
AT + CGMF=1<CR>
AT + CGMS= “ 13605696031 ” ,129<CR>
>Hello World!<^Z>
1.1.4. Pdu 模式
pdu 编码主要包括两个主要的部分,一是 pdu 串的整体数据格式,分别因为发送信息串和接收信息串而有区别,二是 pdu 中文本部分的编码,分别因为字符集而不同。
我们也可以这样来理解这个 pdu 编码的格式, sms 相当于一个协议栈,最简单的协议栈:
根据 gsm03.40 规范, sms 协议包括以下几层:
1、 SM-AL :应用层。这个部分就是数据部分。
2、 SM-TL :传输层。我们可以清楚的看到这里描述了主要的短信内容,包括发送号码,接收号码,信息类型,编码,数据报长度等等,这也是我们编程主要要面对的问题。
3、 SM-RL :中继层。这个指的是短信在网关之间中继需要的协议。
4、 SM-LL: 链路层。
从上述描述中我们可以清楚的看到,我们编程主要集中于传输层。
PDU 串的用户信息 (TP-UD) 段最大容量是 140 字节,所以在这三种编码方式下,可以发送的短消息的最大字符数分别是 160 、 140 和 70 。这里,将一个英文字母、一个汉字和一个数据字节都视为一个字符。
1.2. SMS 用户数据的编码方法
1.2.1. 英文 7 位编码
图片不能正确显示
这是 gsm 的默认编码方式
由于这样的移位,我们可以看到我们能发的最多英文字符等于: 140*8/7 = 160 。
1.2.2. 数据 8 位编码
8-bit 编码通常用于发送数据消息,比如图片和铃声等;
1.2.3. 中文 pdu 编码
发送中文时,必须用 UCS2 ( utf-16 )进行编码,最多可以发 140/2 = 70 个汉字。
UniCode 编码转换也比较简单,以中文为例,一个中文字符是两个字节,直接对高位字节和低位字节进行十六进制转换就可以了。如“欢迎”, UniCode 编码是 6B22 8FCE ,这同时也就是转换的结果,如果发送的串中有英文字符,那么在前面补全 00 ,以保证一个字符对应两个字节。
1.2.4. Wap-push 中的中文编码
做 wap-push 短信的时候有些问题了,开始的时候也按照 Unicode 编码处理,总是失败,后来才发现,有个编码字段设为了 uft-8 ,所以在这种情况下,还是可以出现其他编码方式的。
1.3. 短信报头分析
1.3.1. 短信类型
详细请参考 gsm 0438 规范和 gsm0440 规范,里面有详细的关于各种短消息类型的描述。
在 sms 中到底支持多少种类型的短信,短信类型由什么进行控制,这是我们在这里需要着重介绍的问题。
在传输层来分,一共有六大短信类型: SMS-DELIVER , SMS-DELIVER-REPORT , SMS-SUBMIT
, SMS-SUBMIT-REPORT , SMS-STATUS-REPORT , SMS-COMMAND ,这六种短信类型,由短信中心地址后的第一个字节的最低两位控制。
bit1 |
bit0 |
Message type |
0 |
0 |
SMS-DELIVER (in the direction SC to MS) |
0 |
0 |
SMS-DELIVER REPORT (in the direction MS to SC) |
1 |
0 |
SMS-STATUS-REPORT (in the direction SC to MS) |
1 |
0 |
SMS-COMMAND (in the direction MS to SC) |
0 |
1 |
SMS-SUBMIT (in the direction MS to SC) |
0 |
1 |
SMS-SUBMIT-REPORT (in the direction SC to MS) |
1 |
1 |
Reserved |
也就是说,每个短信在短信中心地址之后的第一个字节的最低两位是至关重要的。他决定了如何读这条短信(结合是发送的,还是接收的)
1.3.2. 地址编码
短信发送中都会涉及到短信地址的问题,他们的编码规则是一致的 , 简单来说就是 BCD 8421 码 编码。
如: 08 91 683108501505F 0 ,
08 :地址长度,(号码类型 + 号码长度) /2 的十六进制表示
91 :号码类型
683108501505F 0 :号码,实际号码应为: 8613805515500 ,号码处理方法为 , 如果为 +86 开始 , 将 + 号去掉 , 然后判断是否为偶数 , 不是在末尾补 F, 然后将奇数位和偶数位互换
1.3.3. TP-DCS( 数据编码格式 )
这个字节比较特殊,表明整个短信的字符编码,数据内容等信息。详细说明参考 gsm03.38 规范。
1.3.4. 第一个字节
Pdu 编码的第一个字节比较有意思,这个字节会根据六种不同的短信按位有不同的意思,拿句专业一点的话来说,叫 bitmask. 用图来大概描述一下,详细参考 gsm0340 的 9.2.3 段。
位数 |
MSG_Deliever |
MSG_SUBMIT |
7 |
TP_RP (回复地址) |
TP_RP |
6 |
TP_UDHI (数据报头) |
TP_UDHI |
5 |
TP_SRI (需要回复) |
TP_SRR (请求回复) |
4 |
|
TP_VPF( 时间格式 ) |
3 |
|
|
2 |
TP_MMS (多条短信标志, 1 为无, 0 为有) |
TP_RD( 拒绝重复标志 ) |
1 , 0 |
TP_MTI (短信类型) |
TP_MTI |
常见值 |
04 ,正常收到, 44 ,有报头短信 |
11 ,正常发送, 51 ,有报头短信 |
1.3.5. TP-PID (协议标识)
在这个里面还有一个字节比较特殊,就是协议标识。
一般都是 00 ,表示点到点的标准短信。
1.3.6. 超长短信
参考 gsm0340 的 9.2.3 .24TP_UD 部分,这个部分中间的一种情况就是描述超长短信的处理。
长短信关键涉及一个数据报头的问题,数据报头由“长度”和多个“数据元素”组成。
1.3.7. Wap-push 短信
WAP 的推送协议中定义了服务指示( SI : Service Indication )和服务加载( SL : Service Load )两项服务,以给用户和网络运营者更多的选择。服务指示是将新信息的指示和相关的通用资源标识符( URI )推送给用户,由用户选择是立即处理信息还是以后处理。服务加载是将一项服务的 URI 推送给用户,然后客户端自动地使用 PULL 技术根据该 URI 启动服务。两种服务的区别在于用户是否介入推送信息的处理过程。 SL 对推送信息的处理对用户来说是透明的,而 SI 则在指示用户的同时,请用户对随后的处理做出选择。
PUSH 可以将某一站点或某一业务的链接通过短信发送到支持 WAP PUSH 功能的手机上,这样用户只需要阅读这条短信,打开短信中的链接,就可以直接访问业务了。因此, WAP PUSH 实现了短信和 WAP 业务的结合,节省了用户寻找业务的时间,方便用户直接找到并使用自己喜欢的业务。
Wap-push 短信的核心不同之处就在于:
1、 含有数据报头,也就是 TP_UDHI 位为 1 ,一般来说 pdu 的第一个字节发送时为 51 ,接收时为 44 。
2、 TP_DSC 字节不同,一般为 F5 ,表明字符集为 8 位,短信类型为 Class 1; 详细解释参看 gsm03.38 的第四章。
1.4. 编码示例
1.4.1. 发送信息的 PDU 串:
用手机写一条短信息,发送手机号码为 13605696031 ,信息内容为“ Hello World! ”。通过执行 AT + CMGL=2 可以读出此条信息。
AT + CMGL=2 { 读未发短信息 }
+ CMGL: 1,2,,24 {1 表示信息个数, 2 表示未发信息, 24 表示信息总容量 }
08 91 683108501505F 0 11 00 0B 81 3106656930F 1 0000FF 0B E8329BFD06DDDF723619
OK
下面分析这条信息:
08 |
短信息中心地址长度。(短信息中心号码类型 + 短信息中心号码长度 /2 的十六进制表示) |
91 |
短信息中心号码类型, 91 是 TON/NPI 。 TON/NPI 遵守 International/E.164 标准,指在号码前需加‘+’号 ; 此外还可有其他数值,但 91 最常用。 |
683108501505F 0 |
短信息中心号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为: 8613805515500( 字母 F 意指长度减 1), 这是作者所在地 GSM 短信息中心的号码。 ( 号码处理方法为 , 如果为 +86 开始 , 将 + 号去掉 , 然后判断是否为偶数 , 不是在末尾补 F, 然后将奇数位和偶数位互换 ) |
11 |
文件头字节 (header byte, 是一种 bitmask) 。这里 11 指正常地发送短信息。 |
00 |
信息参考号。( TP-MR ) |
0D |
被叫号码长度。被叫号码长度的十六进制表示。 |
81 |
被叫号码类型。 |
3106656930F 1 |
被叫号码,也经过了移位处理,实际号码为 13605696031 。 |
00 |
协议标识 (TP-PID), 是普通 GSM 类型,点到点方式 |
00 |
用户信息编码方式 (TP-DCS) , 7-bit 编码( 08 : UCS2 编码) |
FF |
有效期 (TP-VP), 短信的有效时间 |
0B |
短信息长度 |
E8329BFD06DDDF723619 |
短信息内容“ Hello World! ”。 |
1.4.2. 接受信息的 PDU 串
读取以上发送出来的短信,可以收到如下信息 , 接受到来自 13600554267 的“欢迎“ PDU 串为: 0891683108503705F0040D91683106504562F7000830507001021500046B228FCE 。而接受到的“欢迎“ PDU 串为:
0891683108503705F0040D91683106504562F70000305070010201000AE8329BFD4697D9EC37 。对以上的 PDU 串分析如下表:
段 |
含义 |
说明 |
08 |
SMSC 地址信息的长度 |
共 8 个八位字节 ( 包括 91) |
91 |
SMSC 地址格式 (TON/NPI) |
用国际格式号码 ( 在前面加 ‘+’) |
683108503705F 0 |
SMSC 地址 |
8613800573500 ,补 ‘F’ 凑成偶数个 |
04 |
基本参数 (TP-MTI/MMS/RP) |
接收,无更多消息,有回复地址,如果为 00 ,就没有以下关于回复地址的三个段 |
0D |
回复地址数字个数 |
共 13 个十进制数 ( 不包括 91 和 ‘F’) |
91 |
回复地址格式 (TON/NPI) |
用国际格式号码 ( 在前面加 ‘+’) |
683106504562F 7 |
回复地址 (TP-RA) |
8613600554267 ,补 ‘F’ 凑成偶数个 |
00 |
协议标识 (TP-PID) |
是普通 GSM 类型,点到点方式 |
08 |
用户信息编码方式 (TP-DCS) |
UCS2 编码(即中文) |
30507001021500 |
时间戳 (TP-SCTS) |
2003-3-12 08:36:45 +8 时区 |
04 |
用户信息长度 (TP-UDL) |
实际长度 4 个字节 |
6B228FCE |
用户信息 (TP-UD) |
“ 欢迎 !” |
1.4.3. 超长短信
所谓超长短信不同的地方无非就是数据报文需要有个拼接的过程,这个详细可以参考 gsm03.40 的 9.2.3 .24.1 段。下面是个例子,表明的是短信的第一条和第二条。
第一条
0891683108100005F0 |
SMSC 地址 |
44 |
有协议头标志 |
0D91683118216553F6 |
回复地址 |
0008 |
TP-PID , TP-DCS |
60403011142423 |
时间戳 (TP-SCTS) |
8C |
用户信息长度 (TP-UDL) |
05 |
协议头的长度 |
00 |
标志这是个分拆短信 |
03 |
分拆数据元素的长度 |
39 |
唯一标志(用于把两条短信合并) |
02 |
一共两条 |
01 |
这是第一条 |
4E 8C 96F 64E005B 9A 4 F 1A 597D597D597D76 8465F 665F 665F 695F 4 4E0D597D597D597D 7684 |
数据内容 |
第二条
0891683108100005F0 |
SMSC 地址 |
44 |
有协议头标志 |
0D91683118216553F6 |
回复地址 |
0008 |
TP-PID , TP-DCS |
60403011145423 |
时间戳 (TP-SCTS) |
26 |
用户信息长度 (TP-UDL) |
05 |
协议头的长度 |
00 |
标志这是个分拆短信 |
03 |
分拆数据元素的长度 |
39 |
唯一标志(用于把两条短信合并) |
02 |
一共两条 |
02 |
这是第二条 |
81EA4ECE524D 5C 317761 |
数据 |
1.4.4. Wap-push 短信
发送的 pdu ,关于 wap-push 短信中间的 wbxml 该如何转变和编码,请参考 WAP Service Indication 规范。
0891683108100005F0 |
SMSC 地址 |
51 |
有协议头标志 |
00 |
TP_MR 消息基准值 |
0D91683118216553F6 |
回复地址 |
00 |
TP-PID |
F5 |
TP-DCS |
A7 |
有效期 TP-VP |
85 |
用户信息长度( TP-UDL ) |
0B |
WAP PUSH 头部的总长度 |
05 |
协议头的长度 |
00 |
标志这是个分拆短信 |
03 |
分拆数据元素的长度 |
03 |
唯一标志(用于把两条短信合并) |
01 |
一共一条 |
01 |
这是第一条 |
05040B 8423F 0 |
表示接下来是一个 WAP PUSH |
29060603AE81EA8DCA |
WSP |
02 |
标记位 |
05 |
-//WAPFORUM//DTD SI 1.0//EN |
6A |
UTF-8 |
00 |
标记开始 |
45 |
<si> |
C6 |
<indication |
08 |
<action=signal-high> |
0C |
href="http:// |
03 |
字符串开始 |
3231312e3133362e31353 |
URL |
00 |
URL 字符串结束 |
01 |
> |
03 |
内容描述字符串开始 |
E8AFB7E782B9E587BB |
内容描述字符串 |
00 |
内容描述字符串结束 |
01 |
</si> |
01 |
</indication> |