WAP PUSH解析(1)——SMS PDU编码

转自:http://blog.csdn.net/thl789/article/details/7704127


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

 

一、单个SMS PDU的封装


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

[plain]  view plain copy
  1. 0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a  
  2. 0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38  
  3. 3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689  
  4. 8be69cbae8af81e588b8e38082000101  

(注:因显示的原因,人为的进行了分行,其实这个包中间并没有换行)

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


1. 短信中心

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

 

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

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

 

2. FirstByte:

 
[plain]  view plain copy
  1. 0x44 = 0100 0100  
  2. bit1.bit0: mti  
  3.       00 Delevery  
  4.       01 Submit  
  5.       10 Status Report  
  6. bit7: TP-Reply-Path  
  7.       1 有  
  8.       0 无  
  9. bit6: 指示是否有userdata header (UDH)  
  10.       1 有  
  11.       0 无  
  12. bit4.bit3: TP-Validity-Period (submit类型的PDU才有意义)  
  13.       00: len=0  
  14.       10: len=1  
  15.       01/11: len=7  

 

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

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

 

3. 发送方地址(Originating address)

 
[plain]  view plain copy
  1. 地址长度:   
  2.   长度Length = 08   
  3.   得到地址占用的字节数(包含长度本身): 2 + (Length + 1) / 2 = 6  
  4.   地址在08a001560886  
  5. 08 a001560886  
  6. TOA: 0xA0 = 1010 0000  
  7.   bit7: 必须为1  
  8.   bit6...bit4: ton = 010  
  9.        000 TON_UNKNOWN(0)  
  10.        001 TON_INTERNATIONAL(1)  
  11.        010 TON_NATIONAL(2)  
  12.        011 TON_NETWORK(3)  
  13.        100 TON_SUBSCRIBER(4)  
  14.        101 TON_ALPHANUMERIC(5)  
  15.        110 TON_ABBREVIATED(6)  
  16. 所以,发送方地址为:  
  17.        01560886   
  18.     -> 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)
 
[plain]  view plain copy
  1.   0x04 = 0000 0100  
  2.   bit7: 如果此位为0  
  3.         bit6: automaticDeletion  
  4.         bit5: userDataCompressed  
  5.         bit4: hasMessageClass  
  6.         if (!userDataCompressed)  // bit5  
  7.            bit3...bit2:   
  8.              00 ENCODING_7BIT  
  9.              10 ENCODING_16BIT  
  10.              01/11: ENCODING_8BIT  
  11.   bit7...bit4: 如果这四位为1111   
  12.         bit2:  
  13.           0 ENCODING_7BIT  
  14.           1 ENCODING_8BIT  
  15.   Bit7...bit4: 如果这四位为1100, 1101 or 1110  
  16.         1110 ENCODING_16BIT(UCS-2)  
  17.         1100/1101 ENCODING_7BIT  
  18.   bit1...bit0: 如果有Class  
  19.         00 CLASS_0  
  20.         01 CLASS_1  
  21.         10 CLASS_2  
  22.         11 CLASS_3  
  23. 所以,这个PDU包数据是8Bit编码,没有Class类型。  

 

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

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

 

6.TP-Service-Centre-Time-Stamp

   短信中心下发的时间戳,这个编码和长度固定
 
[plain]  view plain copy
  1. 21609290251223  
  2.  21 Year:   12  
  3.  60 Month:  06  
  4.  92 Day:    29  
  5.  90 Hour:   09  
  6.  25 Minute: 52  
  7.  12 Second: 21  
  8.  23 TimeZone Byte  
  9.    时区同样高4bit在低位,低4bit在高位  
  10.    Bit3为时区+/-标志位  
  11.    计算的结果为1/4时区  
  12.    0x23 = 0010 0011  
  13.        Bit3: sign symbol  
  14.          0 +  
  15.          1 -  
  16.        0010 x011 -> x011 0010 = 0011 0010 = 32 [quarter-hour]  
  17.    TimeZone: + 32 / 4 = +8  

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

 

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

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

 

7. UserDataHeader – UDH

 
[plain]  view plain copy
  1. UserDataLength: 长度包含UDH和UD,但不包含这个字节本身  
  2.   0x6E = 110  
  3. UserDataHeaderLength: 该长度不包含这个字节本身  
  4.   0x06 = 6  
  5. UserDataHeader: 05040b8423f0  
  6.   UDH中可能有多段,所以要不断解析,直到UDH结束  
  7.   UDH每段含义开头都有个id做标示,接下来是后面具体含义的数据的字节个数,然后才是具体数据  
  8.     
  9.   id - 0x05  
  10.     0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE  
  11.     0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE  
  12.     0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT  
  13.     0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT  
  14.     0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT  
  15.     0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT  
  16.   length: 4  
  17.   dest port: 0b84 -> 0x0B84 = 2948  
  18.       2948 for WAP_PUSH  
  19.   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

 
[plain]  view plain copy
  1. UserDataLength:   
  2.   长度包含UDH和UD,但不包含这个字节本身  
  3.   长度指的是本PDU中的长度  
  4.   PDU[0]: 0x8C = 140  
  5.   PDU[1]: 0x22 = 34  
  6. UserDataHeaderLength: 该长度不包含这个字节本身  
  7.   0x0B = 11  
  8. UserDataHeader:  
  9.   UDH中可能有多段,所以要不断解析,直到UDH结束  
  10.   UDH每段含义开头都有个id做标示,接下来是后面具体含义的数据的字节个数,然后才是具体数据  
  11.   
  12.   PDU[0]: 05040b8423f0 00030b0201  
  13.   PDU[1]: 05040b8423f0 00030b0202  
  14.   
  15.   id - 0x05  
  16.     0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE  
  17.     0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE  
  18.     0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT  
  19.     0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT  
  20.     0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT  
  21.     0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT  
  22.   length: 4  
  23.   dest port: 0b84 -> 0x0B84 = 2948  
  24.     2948 PORT_WAP_PUSH  
  25.   src port: 23f0 -> 0x23F0   
  26.   这段说明这是WAP PUSH的PDU封装  
  27.     
  28.   id - 0x00  
  29.   length: 03  
  30.   ConcatRef.refNumber: 0B  
  31.   ConcatRef.msgCount: 02  
  32.   ConcatRef.seqNumber:  
  33.     PDU[0]: 01  
  34.     PDU[1]: 02  
  35.   这段说明这是长SMS的分拆出来的PDU封装包:  
  36.     refNumber标识是属于哪个长SMS,分拆出来的各个分拆包都有相同的refNumber  
  37.     msgCount长SMS分拆出来的包的个数  
  38.     seqNumber指示到达的该包在各个分拆包中的顺序:取值1.. msgCount  
  39.              因为分拆出来的包到达接收端的顺序不一定是按次序的,所以拼接时,要按照这个顺序。  

 

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中实现》中解读。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值