WAP PUSH是封装在SMS PDU中的,所以要解析WAP PUSH,首先要先看SMS PDU编码,这是SMS / MMS / WAP PUSH等业务的基础。WAP PUSH是通过发送给终端的,所以本文主要看Delivery类型的PDU编码。另外,如果PDU要封装的内容过长,会接收到拆分过的多条SMS,本文对接收到的多条Concatenated SMS的拼接也做了阐述。

一、单个SMS PDU的封装

下面是接收到的一个完整PDU:

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a
0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38
3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689
8be69cbae8af81e588b8e38082000101
(注:因显示的原因,人为的进行了分行,其实这个包中间并没有换行)

SMS PDU的封装并不是在所有的位置都有固定的涵义,它是逐个扫描的,解析完上一个字段,才知道接下来的含义,或者后面字段的长度。

1. 短信中心
   SC长度
      为08,所以接下来的8字节为短信中心内容
   SC 91683108200105f0
      91为国际号,加上’+’号;
      后面的号码编码规则为GSM BCD:683108200105f0 –> 8613800210500
   所以,得到短信中心号码:+8613800210500

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

2. FirstByte:
    0x44 = 0100 0100
    bit1.bit0: mti
          00 Delevery
          01 Submit
          10 Status Report
    bit7: TP-Reply-Path
          1 有
          0 无
    bit6: 指示是否有userdata header (UDH)
          1 有
          0 无
    bit4.bit3: TP-Validity-Period (submit类型的PDU才有意义)
          00: len=0
          10: len=1
          01/11: len=7

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

3. 发送方地址(Originating address)
   地址长度: 
     长度Length = 08 
     得到地址占用的字节数(包含长度本身): 2 + (Length + 1) / 2 = 6
     地址在08a001560886
   08 a001560886
   TOA: 0xA0 = 1010 0000
     bit7: 必须为1
     bit6...bit4: ton = 010
          000 TON_UNKNOWN(0)
          001 TON_INTERNATIONAL(1)
          010 TON_NATIONAL(2)
          011 TON_NETWORK(3)
          100 TON_SUBSCRIBER(4)
          101 TON_ALPHANUMERIC(5)
          110 TON_ABBREVIATED(6)
   所以,发送方地址为:
          01560886 
       -> 10658068

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

4. TP-Protocol-Identifier(TP-PID)
   TS 23.040 9.2.3.9
   01

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

5. TP-Data-Coding-Scheme
 (TS 23.038)
     0x04 = 0000 0100
     bit7: 如果此位为0
           bit6: automaticDeletion
           bit5: userDataCompressed
           bit4: hasMessageClass
           if (!userDataCompressed)  // bit5
              bit3...bit2: 
                00 ENCODING_7BIT
                10 ENCODING_16BIT
                01/11: ENCODING_8BIT
     bit7...bit4: 如果这四位为1111 
           bit2:
             0 ENCODING_7BIT
             1 ENCODING_8BIT
     Bit7...bit4: 如果这四位为1100, 1101 or 1110
           1110 ENCODING_16BIT(UCS-2)
           1100/1101 ENCODING_7BIT
     bit1...bit0: 如果有Class
           00 CLASS_0
           01 CLASS_1
           10 CLASS_2
           11 CLASS_3
   所以,这个PDU包数据是8Bit编码,没有Class类型。

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

6.TP-Service-Centre-Time-Stamp
   短信中心下发的时间戳,这个编码和长度固定
  21609290251223
   21 Year:   12
   60 Month:  06
   92 Day:    29
   90 Hour:   09
   25 Minute: 52
   12 Second: 21
   23 TimeZone Byte
     时区同样高4bit在低位,低4bit在高位
     Bit3为时区+/-标志位
     计算的结果为1/4时区
     0x23 = 0010 0011
         Bit3: sign symbol
           0 +
           1 -
         0010 x011 -> x011 0010 = 0011 0010 = 32 [quarter-hour]
     TimeZone: + 32 / 4 = +8

所以,得到时间戳为:12-06-29 09:52:21 GMT+8

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

7. UserDataHeader – UDH
    UserDataLength: 长度包含UDH和UD,但不包含这个字节本身
      0x6E = 110
    UserDataHeaderLength: 该长度不包含这个字节本身
      0x06 = 6
    UserDataHeader: 05040b8423f0
      UDH中可能有多段,所以要不断解析,直到UDH结束
      UDH每段含义开头都有个id做标示,接下来是后面具体含义的数据的字节个数,然后才是具体数据
      
      id - 0x05
        0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE
        0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE
        0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT
        0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT
        0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT
        0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT
      length: 4
      dest port: 0b84 -> 0x0B84 = 2948
          2948 for WAP_PUSH
      src port: 23f0 -> 0x23F0

PDU是用端口来识别具体业务的,比如这个PDU的目的端口是2948,就是WAP PUSH的PDU封装。
   另外,如果还是长SMS,UDH中还会有长SMS拼接所需要的信息,UDH中就有了多重的含义。

现在PDU扫描到了红色处(绿色部分已经扫描结束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

现在, PDU封装的基本信息已经解析完毕,剩下的是UserData,也已经区分出具体的业务,可以交给具体业务模块去解析。

二、多条SMS PDU的封装

因为单条SMS长度的限制,一条长SMS的发送是拆分成多条SMS发送的,接收时也是多条接收,然后拼接。

下面实例是分两次接收到的一条长SMS的两个SMS PDU:

PDU[0]

0891683108200105f04405a02125f00004216092717455238c0b05040b8423f000030b0201790601
ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be58f8be3
8081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280a6e689
8be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6e5bfab
e4b88be8bd

PDU[1]

0891683108200105f04405a02125f0000421609271745523220b05040b8423f000030b0202bde4bd
93e9aa8ce6898be69cbae9a39ee4bfa1000101

UserDataHeader里有多SMS的信息,我们就从这里开始分析。

1. UDH之前部分
PDU[0]与PDU[1]的UDH之前的部分完全相同,与前面讲的单条SMS PDU的封装也相同,所以这里不再赘述这部分的解析。
 
2. UserDataHeader– UDH
    UserDataLength: 
      长度包含UDH和UD,但不包含这个字节本身
      长度指的是本PDU中的长度
      PDU[0]: 0x8C = 140
      PDU[1]: 0x22 = 34
    UserDataHeaderLength: 该长度不包含这个字节本身
      0x0B = 11
    UserDataHeader:
      UDH中可能有多段,所以要不断解析,直到UDH结束
      UDH每段含义开头都有个id做标示,接下来是后面具体含义的数据的字节个数,然后才是具体数据
 
      PDU[0]: 05040b8423f0 00030b0201
      PDU[1]: 05040b8423f0 00030b0202
    
      id - 0x05
        0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE
        0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE
        0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT
        0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT
        0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT
        0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT
      length: 4
      dest port: 0b84 -> 0x0B84 = 2948
        2948 PORT_WAP_PUSH
      src port: 23f0 -> 0x23F0 
      这段说明这是WAP PUSH的PDU封装
      
      id - 0x00
      length: 03
      ConcatRef.refNumber: 0B
      ConcatRef.msgCount: 02
      ConcatRef.seqNumber:
        PDU[0]: 01
        PDU[1]: 02
      这段说明这是长SMS的分拆出来的PDU封装包:
        refNumber标识是属于哪个长SMS,分拆出来的各个分拆包都有相同的refNumber
        msgCount长SMS分拆出来的包的个数
        seqNumber指示到达的该包在各个分拆包中的顺序:取值1.. msgCount
                 因为分拆出来的包到达接收端的顺序不一定是按次序的,所以拼接时,要按照这个顺序。

3. UserData

这是一条长SMS拆分出的两条,所以UserData要按seqNumber次序拼接起来。

PDU[0]

0891683108200105f04405a02125f00004216092717455238c0b05040b8423f000030b0201790601
ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be58f8be3
8081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280a6e689
8be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6e5bfab
e4b88be8bd
PDU[1]

0891683108200105f04405a02125f0000421609271745523220b05040b8423f000030b0202bde4bd
93e9aa8ce6898be69cbae9a39ee4bfa1000101
 
把PDU[0]和PDU[1]中的红色的UserData拼接起来,得到完整的UserData。
 
790601ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be5
8f8be38081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280
a6e6898be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6
e5bfabe4b88be8bdbde4bd93e9aa8ce6898be69cbae9a39ee4bfa1000101
 
至此,完整的UserData已经得到,在UDH中也已经区分出具体的业务,可以交给具体业务模块去解析。

三、小结

Delivery SMS PDU中可以解析出:Service Centre(可无)、有无UDH、PDU类型的识别、发送方号码、TP-PID、编码格式、Class类型(可无)、时间戳、UDH(可无。含:UserData长度、UserDataHeader长度,可能有端口号或Concat信息,等)以及包含具体业务数据的UserData。

关于UserData中具体WAP PUSH业务的封装格式,在后续文章《WAP PUSH解析(2)——WSP以及WBXML编码》和《WAP PUSH解析(3)——Android中实现》中解读。

WAP PUSH解析(1)——SMS PDU编码相关推荐

  1. [原]Wap push over sms 实践

    Wap push over sms 实践  author:clapton_xpAThotmailDOTcom 20060323 通过短信进行点对点的WAP PUSH,本质上来说应该是发送一个wap页面 ...

  2. Create WAP Push SMS Messages

    转自:http://blog.163.com/htlxyz@126/blog/static/1685940292009620111811387/ 改过后的代码在下面,程序好像可以输出了WAPPUSH的 ...

  3. SMS短信的PDU编码规则

    先来看两张图: 1. 发送方PDU格式SMS-SUBMIT-PDU *1Message type (1 octet)                                           ...

  4. android wap push实现

    WAP PUSH Date Ver Description Author Reviewer 2011-9-5 0.0.1 Draft 1. Wap Push简介: Wap Push分为两种:SI(Se ...

  5. PDU编码(非常经典)

    共有三种方式来发送和接收SMS信息:Block Mode, Text Mode和PDU Mode.其中PDU Mode被所有手机支持,可以使用任何字符集,这也是手机默认的编码方式. 发送短消息常用Te ...

  6. SMS PDU 短信回执设置

    以前做的一个东西,把资料整理了一下. 今天研究了一个上午的sms pdu 格式,找到了在pdu串中设置短信回执的方法.就是在pdu-type这个8位位组一般都设置为11:包含TP-MTI(2bit), ...

  7. java usc2短信编码_手机短信PDU编码与解码

    编码代码: / ///文 件:PDUdecoding.cs ///程 序 员:klude ///编制日期:2007-11-04 ///概 要:针对国内短信编码(USC2) ///组成结构:包含四个函数 ...

  8. 手机 SMS PDU 格式参考手册

    开发者指南 SMS with the SMS PDU-mode 翻译整理: 犬犬(心帆) E-Mail: shuixin13@163.com 最后修定日期: 2004-10-18 SMS with t ...

  9. WAP Push SP接口协议

    1.术语说明 1)      DSMP Data Service Management Platform,数据业务管理平台.中国移动集团公司的移动数据业务平台,移动梦网计划(Monternet)的核心 ...

  10. Wap Push 源码

    Wap Push 源码 CMPP3.0 , C# 源码 submit.TP_pID=0 submit.TP_udhi=1 submit.Msg_Fmt=0x04 WAPPUSH wap=new WAP ...

最新文章

  1. 使用WindowsLive Writer2012和officeWord2013发布到博客园全面总结
  2. 游戏编程十年总结(下)(转)
  3. 启动文件需要做的工作
  4. .NET Core 3.0之深入源码理解Startup的注册及运行
  5. CentOS 7.1下KVM的安装与配置
  6. (bfs)连连看(hdu1175)
  7. 开工第一天,老板补发年终奖,一箱18元的冰棍
  8. 超大规模集成电路先进光刻理论与应用_中科院上海光机所光刻机投影物镜热效应模型研究取得进展...
  9. python图例重复显示_python – 具有两个标记的多行的自定义图例,用于相同的文本...
  10. JAVA学习之旅番外篇
  11. github 学习笔记【一】
  12. 2019最新PHP100项目实战(PHP新手入门教程)
  13. Linux系统安全及应用详解
  14. 如何查询芯片 IC 元器件 的datasheet数据手册
  15. 主题:讲解三层代码讲解--第三课(*****) DATE:2004-05-28
  16. Jlink之J-Scope虚拟示波器
  17. WinForm通过Excel作为中间介质实现导入导出小工具
  18. java中随机点名器的简单程序
  19. csapp之lab:shell lab
  20. IDEA 2020.1官网汉化插件安装

热门文章

  1. k210 hc-05 智慧课堂 人脸识别签到
  2. 基于MATLAB的战术手势识别功能的设计与实现
  3. opencv4找不到opencv2/core/core.hpp: No such file or directory
  4. Mac电脑版微信】双开方法,最简单的微信多开教程
  5. 【安卓作业】星座查询小程序
  6. UniWebView 3 使用心得
  7. de4dot使用教程
  8. 如何委婉地拒绝公司的offer?
  9. 高速电路设计与仿真之PCB篇(一)
  10. vb.net mysql 实例教程_VB.NET数据库编程基础教程(转载