Android Mms:PDU介绍(协议数据单元)
发布日期:2021-06-30 21:23:22 浏览次数:3 分类:技术文章

本文共 26309 字,大约阅读时间需要 87 分钟。

        MMS PDU(Protocol Data Unit,协议数据单元)由MMS头和MMS消息体组成,MMS头由多个域名和域值组成,由客户端指定, MMS头里面的一些域可以被MMS Proxy-Replay修改或补充,MMS Proxy-Replay使用这些头域信息生成MM通知以及构造接收MMS PDU中的相关头域,连同消息实体一同送往接收方。消息体跟在MMS头之后,大多数MMS PDU只含有MMS头,它们起到建立和维持通信的作用,只有在M-Send.req和M-Retrieve.conf PDU中才有消息体。

    Android当中的Mms对MMS(Multimedia Messaging Service)的操作关乎MMS协议部分都是通过Frameworks中提供的API来完成的:com.google.android.mms这个包在SDK中是不开放的,只能供内部程序使用,它封装了所有MMS所需要的API。

       

  这个包就是Android中对MMS协议的实现,包括一些数据结构:GenericPdu,MultimediaMessagePdu,SendReq,SendConf,NotificationInd,RetrieveConf,PduHeaders,PduBody,PduPart等。

       也包括操作这些数据的类:PduPersister,PduParser和PduComposer。PduPersister主要供给Android内部的应用程序使用;而PduParser和PduComposer会涉及到PDU相关的协议,会与MMSC或其他平台有相互影响(比如所打包的字节流是否符合标准,能否被其他平台成功解析和识别等)

       这个包的功能就是在发送时把多媒体数据打包成标准MMSC能识别的PDU格式数据,在接收时把PDU数据包解析出来以供更加方便的应用程序使用,同时也提供一些存储上的接口,比如把PDU保存到数据库,从数据库加载出PDU。
 

Class    Purpose
PduPersister  用于管理PDU存储
PduParser 用于解析PDU
PduComposer 用于生成PDU
PduPersister 用于管理PDU存储,关键的方法:

PduPersister: 用于管理PDU存储,关键的方法:

Return Method Description
PduPersister getPduPersister(Context) Get the object
Uri persist(GenericPdu, Uri) 把一个GenericPdu保存到Uri所指定的数据库中,返回指向新生成数据的Uri
GenericPdu load(Uri) 从数据库把Uri所指的数据加载出来成一个GenericPdu对象
Uri move(Uri, Uri) 把Pdu从一个地方移到另一个地方,比如从草稿箱移动到发件箱,当MMS已发送时。

   
为什么会要把PDU的存储也封装成PduPersister呢?因为PDU的存储方式 是放在标准的SQLiteDatabase中,通过TelephonyProvider,而SQLiteDatabase中存储不能以直接的PDU的字节流来存储,必须要把PDU拆解成为可读的字段,因此在存储PDU和从存储加载PDU的过程 中涉及到PDU数据上面的处理,因此封装出来,更方便使用。

PduParser:用于把PDU字节流解析成为Android可识别的GenericPdu

Return   Method  Description
PduParser PduParser(byte[])   Construct an object
GenericPdu parse() 将PDU字节流解析为Android PDU GenericPdu  

PduComposer:把GenericPdu打包生成PDU字节流

Return Method     Description
PduComposer      PduComposer(Context, GenericPdu)  Construct an object
byte[]  make()    Transfer the GenericPdu into a PDU byte stream

 

        MMS PDU和HTTP PDU极为类似,但要简单一些。一个MMS PDU对应一种消息格式。不同类型的MMS PDU有不同的MMS Header 。MMS Header根据WAP-209协议和RFC2387的规定,由一系列的域组成,这些域定义了PDU的各种属性,包括PDU类型,版本号,接受方,发送方,主题,发送时间等。MMS Header中的域分为可选项和必选项,根据PDU的类型不同而不同。

常见的PDU的类型有:

         发送请求:     M-send.req

         发送确认:     M-send.conf

         彩信通知:     M-notification.ind

         通知回应:     M-notifyresp.ind

         获取彩信回应: M-retrieve.conf

         接收确认:     M-acknowledge.ind

         彩信回执:     M-delivery.ind

 

 

    MMS Header后面立即接的就是Message Body。根据MMS Body组装的是否有序(是否有位置控制信息,有显示先后顺序),MMS消息体的组装方式分为:

application/vnd.wap.multipart.mixed方式

 所有的消息内容混合在一起,没有时间上的顺序,内容怎么显示由客户端的显示控制策略来决定。
application/vnd.wap.multipart.related方式
    

      各消息内容之间有一定关系,该关系可能是显示的时间上的先后,显示的位置等。这样在终端显示该消息的时候,就可以以幻灯片的方式显示一系列消息,使得该MM的显示更加趣味化。

         在application/vnd.wap.multipart.related方式的MMS PDU之中,含有显示控制部分“presentation”,而application/vnd.wap.multipart.mixed不含有该部分。

       “presentation”是 MMS 中一个特殊的消息内容(part),它决定了其他消息内容的显示控制信息。实现“presentation”这个消息内容的语言,就是SMIL (Synchronized Multimedia Integration Language)。SMIL是一种简单的标记性语言,内容书写格式和HTML类似。“presentation”正是用SMIL来表示这些多媒体元素显示的次序,位置,开始播放的时间,结束时间。下面给出一个SMIL结构的例子,其中<!—注释-->是注释部分:

例子(包含两帧,每帧包括一张图片和一段文本)

<--!以smil开始--><--!header smil 头-->
<--!显示的底板控制-->
<--!显示的内容定义-->
<--!显示内容控制--><--!第一帧, 持续时间为20秒,显示文件名称是videofilename.3gp -->
<--!第二帧开始,持续2秒-->
<--!第二帧结束-->
<--!smil结束-->

 

      看见了吧,和HTML语言差不多。SMIL写好了以后,在windows平台上,另存为.smil文件以后,可以用支持smil格式的视频播放器打开,前提是smil文件和里面引用到的多媒体元素放在同一个目录里面。

       前面说过,同音频,视频,文本及图片文件这些多媒体元素一样,“presentation”也是一个消息part,它们在Message Body中的排列顺序可以是任意的。还记得前面说过的MMS Header最后一个域Content Type吧,当MM内容包含SMIL格式的表现层时,content type必须为application/vnd.wap.multipart.related,否则使用application/vnd.wap.multipart.mixed。

      客户端怎么知道从哪个部分开始显示呢?当存在多媒体对象和显示控制信息时,即存在“presentation”部分,如果在Content Type中存在Start参数,“presentation”如果不是消息体的第一个part,则必须用start参数指出其所在位置;当不存在Start参数时,“presentation”部分应该排列在第一位的位置上,即紧接在MMS Header后面;当根本不存在“presentation”部分时,如何显示则由客户端的显示策略来决定。

3.3 MMS的封装(Encapsulation)

    对于使用SMIL语言描述的MMS,在通过无线网络发送的时候,我们必须通过一种方式把SMIL和附属的多媒体内容包装在一起,能够以一个unit(整体)的形式发送出去,以便SMIL文件各个部分内容的reference变得有效。

    这个解决的办法就是MIME(Multipart Internet Mail Extensions)规范,这个规范的最初作用是在email的plain text的主体中加入不同的内容。比如说,发送带有附件的email,这个时候你就使用了MIME的规范。MIME负责把所有的独立的文本、图像、声音、视频内容以及SMIL文件本身捆绑在一起,用于告诉接受的终端这个MMS的内容是相互相关(related to one another)并且相互参考的(referenced to one another)。MIME规范(RFC2045-2049)和OMA制定的Multimedia Messaging Service Encapsulation Protocol规定的二进制码格式有一一对应的关系。

 

MIME封装示例

下面是根据RFC文档给出的MIME的封装示例:

Content-Type: application/vnd.wap.multipart.related; boundary="boundary-example"; type="application/smil"--boundary-exampleContent-Type: text/html; charset="US-ASCII"... ...  ... ...... ...  ... ...--boundary-exampleContent-Type: image/gifContent-ID: 
Content-Location: fiction1/fiction2…………………..Gif data--boundary-exampleContent-Type: image/gifContent-ID:
Content-Location: fiction1/fiction3…………………..Gif data--boundary-example--

Content-type

位于信息头部的content-type用于通知接收的终端消息的各个不同部分的内容是相互关联的、并且可能是相互索引的(refer to one another)。而在信息体里面的Content-Type用来指定该部分内容的数据类型。

Boundary

Boundary参数指定分隔符,用于分割各个不同的消息part。分隔符以两个短杠“-”开头。第一个部分是一个html类型的消息,这里只是取得了相关的部分。第二和第三部分省略了实际的images图像的实体。

Content-Location 和 Content-ID

在HTML文本部分我们可以看到,我们可以利用两种方式来索引消息内容的不同部分。这两种不同的方式是 content-ID 和 content–Location。这两个域的属性应该是唯一的,以便区分不同的数据块。

如果一部分的消息体想通过content-ID指向(refer to)另外一部分的消息体,可以使用“CID”。关于MIME的部分的信息可以参考RFC文档(RFC2387和RFC2357)。

Multipart data

 

Message Body的结构正如上面MIME的封装结构。在实际的MMS PDU中,为了压缩数据,每个域的域名用固定的字节编码,并且去掉了分隔符。Message Body多媒体数据(Multipart,对应于多媒体文件数据)的编码结构如图12所示:

图12 Application/vnd.wap.multipart 的格式

 

图13 uintvar变量结构

 

整个uintvar变量的长度少于5 byte因此,uintvar可以表示无符号整型数的表示范围(0~32bit)。实际使用过程中,先把要编码的数值的二进制从最低位按每7位一组分好,然后把它们填到PayLoad域中,高位不足的补零,举例说明

数值0x8715(1000 0111 1010 0101)编码成uintvar类型如下所示:

图14 0x8715的uintvar表示

 

注意,如果高7位正好是7个零的话,不能编码成0x80,而是略去该字节。

Entries域结构如表2所示:

表2 Entries结构

 

HeaderLen指示ContentType域和Header域的总长度,是一个Uintvar变量,DataLen指示后面Data域的长度,在这里指的是一块多媒体数据的字节数,ContentType域用来表示后面的数据块是什么类型的数据(如txt文本,jpeg图片,还是vidoe数据流),已经注册过的类型编码值可见附录A。Header域指定该块数据的其它信息,其中最重要的是Content Location和Content ID值,因此,在Message Body部分,Header域是不能省略的。Content Location和Content ID值通常是多媒体数据的文件名,Content Location域以单引号“””开始,后面一对<>里面包含文件名,Content ID域则直接就是一对<>里面包含文件名,关于这两个域的格式可参考MIME 的Part one,该部分在rfc2045里面。接着Header的是Data域,它的长度由DataLen指定,现在应该明白为什么MMS中的Message Body的MIME封装中不需要分隔符了吧,每个域的长度都是指定的。

    一个Entries域的后面紧接着另外一个Entries域(如果有的话),直到整个的MMS PDU尾,smil部分也是一个Entries。

3.4 MMS PDU封装示例

下面举一个实际的MMS PDU编码示例来结束本节,该MMS是multipart/related类型。

实际发送MMS PDU完整的十六进制编码如下,为了节省篇幅,用“……”代替多媒体的具体数据:

 

8c 80 98 33 36 35 38 32 34 00 8d 92 89 1a 80 2b38 36 31 33 34 36 39 30 37 32 34 30 34 2f 54 5950 45 3d 50 4c 4d 4e 00 97 2b 38 36 31 35 38 3734 32 38 39 37 36 36 2f 54 59 50 45 3d 50 4c 4d4e 00 96 62 69 67 20 4d 4d 53 00 84 1f 1f b3 8a3c 62 69 67 2e 73 6d 69 6c 3e 00 89 61 70 70 6c69 63 61 74 69 6f 6e 2f 73 6d 69 6c 00 05 28 837c 61 70 70 6c 69 63 61 74 69 6f 6e 2f 73 6d 696c 00 c0 22 3c 62 69 67 2e 73 6d 69 6c 3e 00 8e62 69 67 2e 73 6d 69 6c 00 3c 73 6d 69 6c 3e 0d…………………………………………………………….………………….22 b7 63 9e c0 22 3c 6c 69 6e 6d65 69 6d 65 69 2e 6a 70 67 3e 00 8e 6c 69 6e 6d65 69 6d 65 69 2e 6a 70 67 00 ff d8 ff e0………………………………………………………… 1e d9 269d c0 22 3c 6c 6f 67 6f 5f 63 6e 2e 67 69 66 3e00 8e 6c 6f 67 6f 5f 63 6e 2e 67 69 66 00 47 49……………  18 e4 36 9d c0 22 3c 32 30 30 38 2e67 69 66 3e 00 8e 32 30 30 38 2e 67 69 66 00 47………………… 1c cd 15 9d c0 22 3c 6d 6f 6e 6b65 79 2e 67 69 66 3e 00 8e 6d 6f 6e 6b 65 79 2e67 69 66 00 47 49 46………………………………….……………………………………………………………..

 

上面青绿色和深黄色部分是MMS PDU Header,灰色部分是Multipart Header,下面是对上面数据的分析:

8c 80

80:即0C的最高位置1 表示X-Mms-Message-Type;

8C:m-send-req类型的PDU

98 33 36 35 38 32 34 00

98:0x18+0x80 X-Mms-Transaction-ID

33 36 35 38 32 34 00:365824的ASCⅡ编码,最后以00结尾

8D 92

8D:X-Mms-Version 92: 1.2, 高4位9是主版本号1+8,低4位是次版本号2

89 1A 80 2B 38 36 31 33 34 36 39 30 37 32 34 30 34 2F 54 59 50 45 3D 50 4C 4D 4E 00

89:From ;

1A:From域的长度

80:值域的类型

2B~4E:+8613469072404/TYPE=PLMN,最后以00结尾

97 2B 38 36 31 35 38 37 34 32 38 39 37 36 36 2F 54 59 50 45 3D 50 4C 4D 4E 00

97:TO

2B~00:+8615874289766/TYPE=PLMN

96 62 69 67 20 4d 4d 53 00

96:Subject

62~53 00: big MMS 最后以00结尾

84 1f 1f b3 8a

3c 62 69 67 2e 73 6d 69 6c 3e 00 89 61 70 70 6c

69 63 61 74 69 6f 6e 2f 73 6d 69 6c 00  

84:Content-Type

1f:指示后面一个字节是uintwar长度 

1f:Content-Type的长度为31字节

b3: application/vnd.wap.multipart.related类型,对应于附录A里面的0x33+0x80;

8a:Start参数,见WSP协议Table 38. Well-Known Parameter Assignments,编码值加0x80。

3c~3e 00:<big.smil>的ASC2编码,最后以00结尾

89: Type参数,见WSP Table38

61~6c 00:application/smil,以00结尾

05 28 83

7c 61 70 70 6c 69 63 61 74 69 6f 6e 2f 73 6d 69

6c 00 c0 22 3c 62 69 67 2e 73 6d 69 6c 3e 00 8e

62 69 67 2e 73 6d 69 6c 00

这是Multipart部分,

05:表示后面有5个part

28:HeaderLen,uintvar变量,表示后面的Content-Type和Header有40个字节长度

83 7c:DataLen,uintvar变量,后面数据部分的长度(即smil文件的长度),转化成十进制就是508,

61 70 70 6c 69 63 61 74 69 6f 6e 2f 73 6d 69 6c 00

Content Type域:application/smil的ASC2编码,最后以00结尾

c0 22~3e 00:c0表示这是Content ID域

22~3e是"<big.smil>的ASC2编码,最后以00结尾

8e 62 69 67 2e 73 6d 69 6c 00

8e:表示这是Content Location域

62~6c 00:是big.smil的ASC2编码,最后以00结尾

紫罗兰颜色部分是big.smil文件的具体数据

紧接着的青色部分是linmeimei.jpg部分的Header和数据

22 b7 63 9e c0 22 3c 6c 69 6e 6d

65 69 6d 65 69 2e 6a 70 67 3e 00 8e 6c 69 6e 6d

65 69 6d 65 69 2e 6a 70 67 00 ff d8 ff e0

22:HeaderLen

B7 63:DataLen,uintvar变量

9e:Content Type域,附录A中的image/jpeg 编码0x1e+0x80

c0:Content ID域名编码

22~3e:Content ID值"<linmeimei.jpg>的ASC2编码,最后以00结尾

ff d8 ff e0……:jpg的具体数据

后面的不同颜色部分表示不同的Data part,结构和分析同上,这里不再赘述。

说明:Content Type域名编码可以参照WSP协议说明的Table 39. Header Field Name Assignments,Content Type参数编码可以参照WSP 协议文档的Table 38. Well-Known Parameter Assignments,这两个类型的编码值在MMS PDU中都要把最高位置1,编码值+0x80。其它Header域的编码可参照WSP说明的8.4 Header Encoding章节,每个Header域可以有多种表示方法,其中诸如From,To这些域的格式需要参照MIME相关文档。

 

排版的效果不太理想,在网页上排版不容易呀,好在还插入表格和字体颜色,转载请注明出处。

MMS Header编码

 

 

图10 由系列域名和域值组成了的Header域 

 

预定义的消息域名(Header Name)都由唯一的单字节编码,域值(Header Value)可能是一个单字节,也可能是多字节,这取决于Header Name。表1列出了一些常见的域名及其编码值:

 

表1 常见的域名及其编码

域名

说明

编码

Bcc

密送者地址

0x01

Cc

抄送者地址

0x02

Content-Location

短息通知时用于存放MM所在服务器的Uri地址

0x03

Content-Type

内容类型

0x04

Date

日期

0x05

Delivery-Report

状态报告(默认为不需要)

0x06

Delivery-Time

报告时间

0x07

Expiry

有效期

0x08

From

发送者信息

0x09

Message-Class

信息的类型(个人、广告、信息还是自动)

0x0A

Message-ID

信息ID,识别不同的彩信

0x0B

Message-Type

PDU类型

0x0C

MMS-Version

使用MMS协议的版本

0x0D

Message-Size

MM的大小

0x0E

Priority

优先级

0x0F

Read-Reply

是否需要阅读报告

0x10

Report-Allowed

是否允许报告

0x11

Response-Status

回复状态

0x12

Response-Text

回复文本

0x13

Sender-Visibility

发送者是否可见(即是否匿名发送)

0x14

Status

信息状态(是否立即接收,拒绝还是不支持)

0x15

Subject

主题

0x16

To

接收者地址

0x17

Transaction-Id

传输ID(用于网络控制,识别不同的传输)

0x18

 

 

         在对MMS Header编码时,X-Mms-Message-Type, X-Mms-Transaction-ID和X-Mms-MMS-Version是必须存在的,且它们必须位于MMS Header的开始部分,并且按照前面所列的顺序排列。Content-Type必须在MMS头域的最后,其后为消息体。其它域的顺序可以随意安排。除了常用的消息域外,也可以自定义消息域,自定义消息域以X-开头,但不能以X-Mms-开头。

        这里再强调一次,不同类型的PDU Header包括的域是不尽相同的,在同一个Header里面,有的域是必须存在的,有的域是在某些情况下才存在的,还有的域则是可选的,不同类型PDU Header的详细结构可参见OMA-MMS-ENC-V1_2-20040323-C.pdf 的第6节,详细的Header域名和对应域名的编码可参考OMA-MMS-ENC-V1_2-20040323-C.pdf的第7.2节和7.3节。说明一点:为了是传输的数据更紧凑,WSP协议规定,对于Header Field Name的编码,数值的最高位(即bit7)置1。因此,上述编码值在实际的MMS PDU中需要加上0x80。

 

3.2 Message Body

       MMS 在终端上显示出来可以仅仅是一幅画面,也可以像一系列的幻灯片一样,一张接着一张有序地播放,每张“幻灯片”可以包括文字、图像和声音,甚至视频等多媒体元素,元素的显示位置和显示时间可以控制,“幻灯片”之间有一定的时间间隔。这些多媒体元素的数据和显示控制信息通过一定的方式组织起来,经过编码,就组成了MMS PDU的消息体。结构如图11所示:

 

 

图11 MMS PDU结构

      MMS Header在语义上与HTTP协议类似,但是其编码方式并不一样,为了充分利用带宽,MMS Header采用二进制方式编码。Header中的每一个域由域名和域值组成,如下图:

 

基于WSP/WTP的MMS传输——WTP协议的实现

 

WTP协议的实现

      前面给出了一个WSP/WTP/WDP层次结构示意图,采用该协议实现的任何会话都必须通过WTP层,与WSP层不同,WTP没有连接——传输数据——断开连接的过程,它是实现数据的完整正确传输的这样一套协议。WTP有着一整套的完善的分包、丢包检测、重传,数据重组机制。而WSP并不实现这些的功能。其它的话不多说,让我们来看看WTP PUD的结构。

       WTP协议只是在WSP PDU的前面加一个Header,WSP PDU作为WTP的Data域,WTP PDU可以没有Data域。WTP Header包括3~4个字节个固定域和一个不固定的可变域。WTP协议在WAP-224-WTP-20010710-a.pdf里有详细的描述,固定域有下表列出的7种类型PDU:

表3 WTP PDU类型及其编码

       Note 2 所示的是WTP可选的支持功能,但也是比较重要的几种PDU,它们用于分组传输。由于无线网络的特殊性,为了对传输的数据进行精确的控制,WTP允许对每个PDU进行单独而复杂的控制(如包的大小,允许传输延迟时间等),这通过在每个WTP Header的第一个字节置位,然后在Header可变域填充一节或多节称之为TPI的结构进行控制,每个TPI的长度为2~8Byte,同样,TPI是可选的。

5.1 WTP 协议数据单元结构和编码

通用Header域

Continue 标志(CON)

       在每个WTP Header的最开始一个固定的1bit,Continue 标志指出了后面是否接有TPI。如果该标准置位,表示后面有一个或多个TPI,如果清零,则表示WTP Header的可变域是空的,即没有TPI结构。这个标志同样用于每个TPI,用于指定该TPI后面是否还有TPI。置位则表示有,清零表示没有。

Group Trailer (GTR) and Transmission Trailer (TTR) Flag

       翻译成中文就是组尾标记和传输尾标记,这两个标记用于分组传送控制。GTR表明这个WTP PDU包是这组最后一个PDU,TTR表明这个WTP PDU是整个消息的最后一个PDU,一个消息里面可包括多个组,一组里面可以最多有255个PDU。通常GTR和TTR标记组合起来使用,它们的编码如表4所示:

表4  GTR/TTR标志组合

 

       一般的,应该置GTR和TTR位为1,即分组和重传功能无效。在分组传送和重传过程中,如果TTR置位,则GTR标志将被忽略。

Packet Sequence Number(PSN)

       包的顺序号,在分组传送中,这个值用于指定分割包在整个消息中的位置。注意的是该值用一个字节来表示,并且这个域的值不能循环打卷,即如果PSN到了255以后,下一个包不能重新从0开始,所以一个组中最多只能有255个包。

PDU类型

       该域用来指定前面列出来的PDU Type(Invoke,Ack等等)。

Re-transmission Indicator (RID)

       重传标记,如果这个标记置位,表示先前的包传递超时或者丢失或者接收方没有响应,这个包是重传前面的包。

Transaction Identifier (TID)

       我翻译为事务ID,对于每次传输,这个ID是唯一的,并且该值是递增的,每次增1。这样理解它的意义,在应用层,当我们客户端同时发起多个网络请求时,怎么来区分不同请求使用的是哪个或哪些PDU,特别在服务端,由于传输的延迟,先发出的PDU比后发的PDU先收到的情况下,怎么来区分该PDU是对哪个PDU的响应呢。这就是TID存在的必要性。TID号可以循环打卷,即如果到了最大的值,下次又可以从0开始,只是需要把TIDnew标志置1,表示这是新一轮的TID号,以避免和前面的TID混淆(实际上这种可能性很小)。TID占用两个字节。注意一点,如果是客户端向服务器发送PDU,TID的最高位必须清零,如果是服务器端给客户端发送PDU,TID的最高位必须置1,所以实际TID值只有15bit。

       对于WTP Header中任何保留的位,都必须清零,除非有特别说明。

 

5.1.1 WTP Header 域的固定部分结构

Invoke PDU

表5 Invoke PDU结构

 

 

       请求PDU,这种PDU是最重要的PDU之一,当我们需要向网络发送数据也好,请求接收数据也罢,只要是向网络请求服务,都是使用这种类型的PDU。

Invoke PDU中里面通用的域在前面提到过,这里不再说明。Version指明版本号,当前把它清零;TIDnew指定TID是否是新一轮的TID编号,在彩信开发中,一般把它清零;U/P和TCL标志有很大的关系,这里说明一下TCL。

TCL即Transaction Class,中文意思是事务类别。WTP提供三种事务类别,分别是Class 0,Class1和Class2。Class 0是不可靠的数据传输服务,它只管把数据发送出去,而不管对方是否收到,WSP里面不稳定的push方法就是使用的这种类型的事务类型。Class1是可靠的但没有确认的数据传输服务,即我可以保证把数据发给你,但是不管你那边能否及时处理。Class2是可靠的有应答的数据传输服务,即发送端可以保证把数据传递给接收端,接收端对所接收数据及时进行处理以后,需要给发送端一个确认,表示数据处理完毕。这样发送端可以继续发送下一批数据。彩信的传输中我们使用的是Class2事务类型。TCL就是选择所使用事务类型,编码如下,U/P指示在Class2中是否需要发送确认。置1表示需要发送确认,清零表示不需要发送确认。两位Res清零。

表6 Class 编码

Result PDU

       这种PDU用于服务器给客户端一个请求的结果的响应,更多的表示上层WSP服务请求是否成功,如发送彩信时发送是否成功,接收彩信时Result PDU的Data域包括彩信的内容等等。其结构和编码如下表所示,PDU里面的TID是对应Invoke PDU里面的TID,最高位置1。

表7 Result PDU结构

 

Acknowledgement PDU(ACK)

       该类型的PDU仅仅用于WTP层的服务确认,所以该PDU没有Data域。在Class2类型里面,如果服务器需要客户端在接收完数据后发送一个确认 PDU,客户端就发送Acknowledgement PDU给服务端,里面的TID是对应Result PDU里面的TID,最高位清零。PDU结构如下表所示:

表8 Ack PDU结构

       结构里面的Tve/Tok指示:这次消息传输成功完成,注意:如果置1,则表示消息传输失败。如果清零,表示消息传输成功。

Abort PDU

       正如字面意思一样,用于取消本次会话请求。如当彩信正在发送的时候,用户突然不想发送了,这时可以使用Abort PDU来撤消本次会话请求。其PDU结构如下图所示:

表9 Abort PDU结构

       Abort type只有两种取值,0x00表示这是WTP层产生的中止信号;0x01表示这是上层协议产生的中止信号,如WSP层。Abort Reason 指示产生终止的原因,如果Abort type是0x00,则Abort Reason编码见 WAP-224-WTP-20010710-a.pdf的8.3.4.1节的table19。如果Abort type是0x01,则Abort Reason编码见 WAP-230-WSP-20010705-a.pdf附录A中的table19。同ACK Header一样,Abort PDU没有Data域,只是WTP层的服务。

Segmented Invoke PDU

       这种类型的PDU用于客户端向服务器分组传输数据,当需要向服务器发送的数据量很大,而应用程序的收发能力有限时,需要对数据进行分组传送。PDU中前三个字节的内容和Invoke PDU一样,第四个字节是该PDU包在整个消息的位置号,从0开始编号。PDU结构如下表所示:

表10 Segmented Invoke PDU结构

       注意,顺序号为零的分组PDU并不是Segmented Invoke PDU,而是一个GTR和TTR标志清零的Invoke PDU,通过前面对Invoke PDU说明我们知道,Invoke PDU并没有PSN域,但是系统默认其序号为0。所有实际的Segmented Invoke PDU的PSN是从1开始的。

 

Segmented Result PDU

       如果服务器向客户端返回的数据量大于服务端的发送能力或者客户端的接收能力时,就使用该类型 PDU 把要发送的数据分成多个WTP PDU,来响应客户端的请求,PDU的DATA域包含返回的数据。该PDU的结构和Segmented Invoke PDU结构一样,如下表所示:

表11 Segmented Result PDU结构

       经过测试,移动的MMSC返回的Segmented Result PDU是以每5个包为一组,在信号条件一般的情况下,每组平均丢1~2个包,且多发生在数据传送的后面分组中。

Negative Acknowledgement PDU(NAck)

       如果分组的数据在传送过程中丢失了一部分,当接收方接收到带GTR或TTR标志的PDU时,就给发送方发送一个NAck PDU,里面包含丢失的PDU个数和所丢包的序号,然后发送方可以根据NAck PDU所包含的信息,重发这一部分PDU。这里,由于PSN是连续的,我们可以通过检查所接收PDU的PSN是否连续来判断是否有丢包,并且得到所丢包的PSN。

表12 Negative Acknowledgement PDU结构

Packet Sequence Number TPI (Optional)

记得前面提过用于控制WTP PDU传送过程的TPI吧,它是Transport Information Item的缩写,整个WTP协议有7种TPI,这里仅介绍和MMS传输相关的一种(PSN TPI),对于其它几种TPI,可以参照WAP-224-WTP-20010710-a.pdf.的8.4节。TPI位于WTP Header的可变域部分,一个TPI接在一个固定域的后面或者接在一个另一个TPI后面,固定域里面只能是前面七种类型的一种,而可变域里面可以有多个TPI,如果一个固定域或者TPI后面接有另一个TPI,需要把相应的CON标志位置1,否则清零。

       数据接收端在发送端传输完一组WTP PDU后,在没有丢包的情况下,向发送端发送ACK PDU,PSN TPI放在ACK Header中的可变域部分,用于指示接收端已经接收到的WTP PDU顺序号,其结构如下 

表13 PSN TPI结构

 

TPI Length域指定该TPI 后面包含了几个顺序号,一个顺序号占用1byte的空间,由于TPI Length只用2bit表示,所以一个PSN TPI最多只能包含3个顺序号,多于3个顺序号的时候需要用多个PSN TPI(这种情况经常发生)。PSN TPI的TPI Identity域编码为0x03。

到此,用于彩信收发的WTP部分基本知识说完了,下面来介绍应用。

一个WTP PDU最大的长度默认的情况下不超过1400 byte,包括WTP Header,区分于后面介绍的WSP PDU的长度控制,WTP PDU长度即是每次客户端通过无线收发模块一次向无线服务端发送的数据量大小,因此,这个长度值的设定关系到应用程序的功能稳定性。最大延迟时间默认为10s,典型的,在Class2模式下,如果一方发出需要确认的数据后,在这个时间内另一方没有响应的话,发送方会重发上次的数据,实践中发现,对于WAP网关,重发的次数取决于PDU的类型,对于客户端,重发的次数取决于客户端的策略。如果要修改这些值,需要使用Option TPI,其结构可参见WAP-224-WTP-20010710-a.pdf中的8.4.4节。不推荐设定太大长度的PDU,实践中发现,如果指定的PDU长度太长,由于无线网络信号的不稳定性,经常出现应用程序接收线程假死的现象,即线程一直接收不到数据,处于接收等待状态。因此,推荐的WTP PDU大小不超过5k,这样可以取得比较好的稳定性,又不至于收发次数过多。

在Class2模式下,当WTP PDU不超过长度限制的时候,其正常的传输过程如下:

图15 没有丢包情况下的WTP PDU传输

WSP 层向WTP层请求服务,WTP通过以WSP PDU为Data域的Invoke PDU发给服务器,然后服务器返回一个Result PDU,在Result PDU的Data部分包含服务器对WSP请求的响应结果,然后在WTP层,客户端发送一个Ack PDU给服务器,表示Result PDU收到。注意,如果客户端在指定时间内没有作出Ack确认的话,服务器会重发Result PDU。如果客户端一直没有确认,则本次传输做作废处理。

 

 

5.2 WTP 分组传送

       当WSP层的PDU大小大于WTP每次能够传输的最大数据块大小时,就需要把WSP PDU分割成块数据,然后用多个WTP PDU来传输,这个过程对于WSP层服务是不可见的。即只要在WSP PDU大小在WSP层协商的大小范围内,WSP可以把它的PDU交给WTP层处理,而不用关心WTP层的具体处理过程。由于无线网络的数据传输的特殊性,我们一次向服务端传输的数据包不能太大。

先看Class2正常的传输过程,如图16所示:

 

图16 Class2没有丢包情况下的分组传输过程

分组传送的第一个包是Invoke PDU,后面的都是SegmInvoke PDU,整个传输过程的TID是一样的,PSN是递增的,传送完一组,需要接收方给出一个Ack PDU,前面说过,这个Ack PDU后面接了一个或多个PSN TPI,这是必须的。整个消息的最后一个PDU传送完毕以后,接收方对整个消息做一个结果返回,这个Result PDU的Data域包含了对WSP层的结果响应数据。不要忘记,在WTP层,需要再给接收方一个Ack。

当网络信号不好的时候,这种情况是经常存在的,即分组传送过程中存在丢包现象,这时需要我们客户端重传所丢失的PDU,过程如下:

 

图17 Class2丢包的分组传输过程

 

过程中,顺序号为1的PDU丢失了,在检测到TTR标志置位的SegmInvoke PDU后(即该组的最后一个PDU),接收方检查所有收到的PSN号,然后作出Nack应答,Nack PDU没有Data域,它的Header里面包含丢失的PDU的顺序号,这时,发送方重传丢失的PDU,该PDU和前面所丢的包唯一不同的地方就是RID标志是置1的。重传完以后,接收方再给出一个Ack应答。表示该组数据已经完整接收到。为了方便根据顺序号定位丢包的Data域数据,建议每个SegmInvoke PDU的Data域大小固定。

注意,SegmInvoke PDU限于客户端向服务器发送分组数据,而当服务器向客户端返回的结果数据需要分组的话,使用的是SegmResult PDU。这个在接收超过20k大小的彩信时经常用到,这时客户端可以采用与上面接收方一致的应答方法来控制SegmResult PDU的接收过程。

 

 

 

 

 

基于WSP/WTP的MMS传输——WSP 协议的实现

 

        WSP协议位于WTP协议层之上,它没有保证数据正确传送的机制(这个部分是由WTP实现的),在WSP层提供会话管理功能,即连接——交互——断开连接这样的流程,WSP协议与HTTP协议实现上有对应的关系,如果熟悉HTTP,则WSP很容易理解。

       WSP提供两种事务交互模式,无连接模式和有连接模式。无连接模式用于不可靠的信息交互服务,这和WTP的Class0模式比较相像,它不需要对方的回应,比如说彩信的PUSH通知就使用的这种模型。有连接模式提供可靠的数据传送服务,服务请求方发出一个请求,响应方需要给出一个响应以表示请求的结果,彩信应用的就是这种模式。所有应用层的的服务请求都是通过WSP相应的方法(Method)来实现的,服务数据作为WSP PDU的Data域,一个WSP PDU的结构如图18所示:

 

图18 WSP PDU结构

       TID是事务ID,在无连接模式下,该域必须出现;在有连接的模式下,该域不能出现。WSP的功能分为会话管理能力和方法请求功能,Type指出请求的类型,要么是会话管理的子类型要么是方法请求功能的相应的方法类型。Type-Specific Contents包括的有各PDU类型指定的域和应用层的数据,我们这里的数据就是MMS PDU了。下面仅仅介绍几种与彩信传输相关的PDU 类型及其结构。

Connect

       Connect 类型的PDU用于会话开始之前与WAP网关建立连接,同时完成双方的能力协商,即后面会话的一些参数设定。Connect域的结构如表14所示:

表14 Connect域结构

 

       Version 版本号,占用8bit,其编码格式是这样的:高4位放主版本号,低4位放次版本号。WAP-230-WSP-20010705-a.pdf所指的版本号是1.0,编码为0001 0000,即0x10。接着后面的是能力值长度,即Capabilities域的长度,以byte为单位,使用的是大字节序(即高字节放在低地址,低字节放在高地址),这个域的类型是uintvar,前面详细的解释过。

      再接在后面的是HeadersLen,指示Headers域占用的字节数,它也是uintvar类型,和上面的编码规则一样。在MMS的传输中,所有WSP PDU中的Header域都可以省略不填,即HeadersLen可设为0。后面紧跟的是Capabilities域,其结构如表15所示:

表15 Capabilities域结构

 

       开始是长度,是Identifier域和Parameters域长度的总和,uintvar类型,实际中占用1个字节就够了,然后是Identifier,Capability共有10中Identifier,它们的名称、编码值和默认值如下表所示:

 

表16 Capabilitity Identitier域名称及其编码

Name

Encode Value

Default Setting

Client SDU Size

0x00

1400 bytes

Server SDU size

0x01

1400 bytes

Protocol Options

0x02

0x00

Method MOR

0x03

0

Push MOR

0x04

0

Extended Methods

0x05

None

Header Code Pages

0x06

None

Aliases

0x07

None

Client Message Size

0x08

1400 bytes

Server Message Size

0x09

1400 bytes

       实际的WSP PDU 的Encode Value值最高位需要置1。这里和彩信传输相关的有Client SDU Size和Server SDU size两个域,分别用来指定客户端可以接收的最大WSP PDU包的长度和客户端将要发送的最大WSP PDU长度。注意:由于彩信的最大可以有50k,为了一次把彩信数据传送完,这两个值都需设定大于50k。对于其它域的含义和设定值可以参考WSP协议的8.3节。最后面的是Header域,可以不填。

看起来一个完整的Connect PDU如下:

01 10 0b 00 05 80 81 83 e0 00 04 81 86 a0 00

01 //指示是Connect PDU

10 //版本号1.0

0b //CapaliLen 11字节

00 //HeadersLen 0字节

05 //该Capability 域长度为5字节

80 //设定的是Client SDU Size

81 83 e0 00 //60k大小,uintvar编码

04 //该Capability 域长度为4字节

81 //设定的是Server SDU Size

86 a0 00  //100k的uintvar编码

 

ConnectReply PDU

    客户端给服务器发送Connect PDU后,服务端收到以后会返回一个ConnectReply PDU,结构如下:

表17 ConnectReply PDU结构

SenverSessionID 用于后面的Disconnect PDU, 其它域和Connect对应的域一样。注意一点:ConnectReply PDU里面的Capabilities的含义与Connect域里面的不一样,如果服务器接受Connect PDU里面的设定,服务器返回的ConnectReply里面是没有Capabilities的,只有在我们设定的参数服务器有改变是,才在ConnectReply PDU中存在Capabilities域指示,服务器采用的设定值。

DisConnect PDU

    DisConnect PDU里面唯一的一个域是ConnectReply里面的SenverSessionID。用于客户端或服务端断开连接。这个PDU可能是客户端发出的,也可能是服务器发出的。

 

Get PDU

    这个PDU用于向服务器请求数据,用来接收彩信,结构如下:

表18 Disconnect PDU结构

 

里面包含彩信所在服务器的URI地址,URILen指定URI域的长度。URI是在彩信Push通知中取得,一般是一系列的字符串。Header对于接收彩信来说可以省略。

完整的PDU像下面的样子:

0E 00 02 12 40 22 68 74 74 70 3A 2F 2F 32 31 31

2E 31 33 36 2E 32 32 31 2E 37 35 2F 61 52 63 36

78 71 59 66 35 72 72 42

0E 00 02 12 是WTP的Invoke Header部分

40 指定是GetPDU

22 后面的URI域长度是34个字节

68~42 的34个字节是的ASCⅡ编码,彩信的URI地址

POST PDU

    结构如下:

表19 POST PDU结构

这些域不多做解释,这里的Uri域不同于Get PDU里面的Uri域,彩信的传送中指的是彩信服务中心的Uri,对于移动用户来说是:,联通用户是:。ContentType固定为application/vnd.wap.mms-message,Data域是MMS PDU内容。

POST PDU 的完整结构像这样子:

60 19 20 68 74 74 70 3A 2F 2F 6D 6D 73 63 2E 6D

6F 6E 74 65 72 6E 65 74 2E 63 6F 6D 61 70 70 6C

69 63 61 74 69 6F 6E 2F 76 6E 64 2E 77 61 70 2E

6D 6D 73 2D 6D 65 73 73 61 67 65 00 80 8C 98 30

………………………..

60 指定是POST PDU

19 URI长度25字节

20 Header和ContentType总长度32字节

68~6D Uri:http://mmsc.monternet.com 的ASCⅡ编码

61~00 ContentType:application/vnd.wap.mms-message的ASCⅡ编码 00为字串结束符

80 8C 98 30 ……是我们熟悉的MMS PDU内容

 

Reply PDU

       这个是我们用POST方法发送彩信或者用GET方法接收彩信时,服务器给我们应答的WSP PDU,结构如表20:

表20 Reply PDU结构

 

       Status指定请求是否执行成功,和HTTP里面的状态码有一一对应关系,如果执行成功则是0x20,否则是其它的状态码,指定出错的类型,其编码可参考WSP说明文档中附录A的Table36.,如果GET方法执行成功的话,Data域是MMS PDU。

完整的Reply看起来像下面的样子:

13 80 02 04 20 33 61 70 70 6c 69 63 61 74 69 6f

6e 2f 76 6e 64 2e 77 61 70 2e 6d 6d 73 2d 6d 65

73 73 61 67 65 00 a6 52 65 73 69 6e 2f 33 2e 30

2e 37 00 92 04 49 a2 79 95 8c 84 98 30 ………

13 80 02  WTP Result PDU Header部分

04 表示该PDU是Reply PDU

20 状态码,请求成功响应

33 ContentType和Header的总长度

a6 0x26的最高位置1,指明是Header的Server域

52~00 Server域值:Resin/3.0.7

92 Header的Data域

04 Data域值的长度

49 a2 79 95 Data域的值,是从1970年1月1号0点0分0秒到现在的秒数

8c 84 98 30 我们熟悉的MMS Header 后面就是整个的MMS PDU数据。

 

整个WSP/WTP协议就介绍到这里,如果要了解更多的细节,可以参考WAP-230-WSP-20010705-a.pdf和WAP-224-WTP-20010710-a.pdf,这两个文档可以从官方免费下载。

   图19所示的是一个完整的MMS传输过程中的MM相关PDU。其中MMBOX是位于MMS中心服务器上的一块空间,类似于一个“邮箱”,功能及操作和电子邮件的IMAP相近。对于MMBOX的支持是可选的,MMBOX用于存储MM。

 

 

图 19 相对比较完整的MMS传输的过程

由上图可看出MMS传输MM相关的PDU的整个过程为:

    1) MMS客户端发送MM时,MM被封装在称为M-Send.req PDU中,信息以WAP WSP/WTP的协议进行编码,通过无线网络传送到WAP网关,并被转送给MMS Proxy Reply;

    2) MMS客户端通过M-Send.conf PDU接收MMS Proxy Reply返回的信息;

    3) MMS Proxy Reply通过M-Notification.ind PDU通知MMS客户端有新MM到达,MMS通知是以SMS的方式发送的,通知是以WSP协议进行的编码,这个通知里面包含了多媒体信息在彩信服务中心(MMSC)的地址。在没有确认被叫用户已经接受了信息之前,该信息始终保存在短信存储器中。运营商可以通过软件设定保存的时间长度。MMS客户端通过M-NotifyResp.ind PDU进行回应;

    4) MMS客户端从MMS Proxy Reply请求下载MM的操作基于标准的WSP/HTTP GET方法,采用WSP GET.req PDU,MMS Proxy Reply回应下载请求的PDU类型为M-Retrive.conf PDU;

    5) MMS客户端可以向MMS Proxy Reply请求M-Forward.req PDU转发位于服务器上的MM,并获取MMS Proxy Reply回应信息M-Forward.conf PDU;

    6)当MMS客户端发送或转发的MM被接收方成功接收后,如果发送方请求传达报告、接收方允许该操作,则MMS Proxy Reply会向发送方发送传达报告M-Delivery.ind PDU,指示mm传送状态信息,不需要客户端进行回应或确认;

    7)当发送方要求已读报告、接收方允许己读报告时,MMS客户端产生M-read-rec.ind PDU发送给接收方的分发代理,由其转发给原始发送方的分发代理,后者接收到M-read-rec.ind PDU后,产生一个M-read-orig.ind PDU并将其发送到MMS客户端来传送已读报告;

    8) MMS客户端通过M-Mbox-Store.req PDU和M-Mbox-Store.conf PDU将新到MM存储到MMBOX,或更新已在MMBOX中的MM的状态和标记;通过M-Mbox-View.req PDU向MMS Proxy Reply请求位于MMBOX中的一个或多个MM的信息用于浏览,也可以获取指定的MM的内容;通过M-Mbox-Upload.req PDU将本地的MM上传存储到MMBOX中;通过M-Mbox-Delete.req PDU请求MMS Proxy Reply删除位于MMBOX中的MM. MMBOX中的MM均有MM标记属性,其由客户端进行维护,主要用于客户端检索、过滤MM之用,这些功能支持是可选的。

下面是MMS客户终端系统需要处理的20种MMS PDU:

    1.客户端将MM发送给MMS Proxy Reply (M-Send.req )
    2.MMS Proxy Reply中继发送给客户端(M-Send.conf )
    3.从MMS Proxy Reply取回消息(WSP/HTTP GET.req )
    4.接收MM回复,MMS Proxy Reply发送至客户端(M-Retrieve.conf )
    5.新MM到达通知,MMS Proxy Reply发送至客户端(M-Notification.ind )
    6.MM通知回复,客户端发送至MMS Proxy Reply (M-NotifyResp.ind )
    7.己发送消息的发送报告(M-Delivery.ind )
    8.应答发送的消息(M-Acknowledge.ind )
    9.已发送消息的阅读报告(M-Read-Rec.ind, M-Read-Orig.ind)
    10.转发消息(MMS客户端发送一个请求让MMS Proxy Reply转发消息  M-Forward.req和M-Forward. conf )
    11.存储或更新消息(M-Mbox-Store.req, M-Mbox-Store.conf)
    12.浏览下载消息(M-Mbox-View.req, M-Mbox-View.conf)
    13.MMBOX上传操作(M-Mbox-Upload.req, M-Mbox-Upload.conf)
    14.MMBOX删除操作(M-Mbox-Delete.req, M-Mbox-Delete.conf)

    MMS服务的实现是通过MMS客户端和MMS Proxy Reply之间相互唤起和响应来传递信息的,这些传输流包括MM信息和相应的响应状态信息等。而这些MM信息被封装在相关的PDU中进行传输。这里再强调一下,实际的数据发送与接收是在客户端与WAP网关之间。MMS客户端和MMS Proxy Reply通过WAP网关传递信息。WAP 1.x网关上,每种MMS PDU有对应的WSP协议实现,MMS与WSP的对应关系可参见OMA-MMS-CTR-V1_2-20031215-C.pdf的第8节Binding to Transport Protocols,里面有详细的说明。

 

基于WSP/WTP的MMS传输——完整MMSWSP/WTP打包示例

 

最后以一个MMS收发过程的WSP/WTP封装过程结束本片文章,假设该MMS小于1k,大于1k的mms用前面介绍的分组传送方法。

收发过程如图21所示:

 

配置

网关:10.0.0.172

网关端口:9201

mmsc uri:http://mmsc.monternet.com

最大发送PDU大小:100k

最大接收PDU大小:100k

retrieve mms Uri: 

 

收发彩信

1.建立连接

发送WSP PDU

WSP PDU Type: Connect

Version: 10

Headers: NULL

Capabilities: 04 80 86 a0 00 04 81 86 a0 00

Header HEX:01 10 14 00 04 80 86 a0 00 04 81 86 a0 00

 

发送 WTP PDU

WTP PDU Type: Invoke

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 1

Version: 0

TIDnew: 0

UACK: 0

TCL: 2

HEX:0a 00 01 02 + WSP PDU(Connect)

 

接收的WTP PDU

WTP PDU Type: Result

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 1

HEX:12 80 01 + WSP PDU(ConnectReply)

 

发送 WTP PDU

WTP PDU Type: Acknowledgement

CON: 0

Tve/Tok: 0

RID: 0

TID: 1

HEX:18 00 01

 

 

接收的 WSP PDU

WSP PDU Type: Connect Reply

Server session id: bb 95 78

Capabilities: 2 83 4

HEX:02 bb 95 78 xx 00 + Header

(注:bb 95 78 是Session ID uintvar类型,xx表示后面Header的长度)

 

2.接收mms

发送 WSP PDU

WSP PDU Type: Get

URI: http://211.136.221.115/aLPk5Ctwv31B

HEX:40 23 + 的ASC编码

 

发送 WTP PDU

WTP PDU Type: Invoke

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 2

Version: 0

TIDnew: 0

UACK: 1

TCL: 2

HEX:0a 00 02 12 + WSP PDU(Get)

 

接收的 WTP PDU

WTP PDU Type: Result

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 2

HEX:12 80 02 + WSP PDU(Reply)

 

发送 WTP PDU

WTP PDU Type: Acknowledgement

CON: 1

Tve/Tok: 0

RID: 0

TID: 2

TPI Type: PSN

CON: 0

Len: 1

PSN: 0

HEX:98 00 02 19 00

 

 

接收的 WSP PDU

WSP PDU Type: Reply

Status: 20

HeadersLen:0x33

ContentType:application/vnd.wap.mms-message

HEX:04 20 33 61 70 70 6c 69 63 61 74 69 6f 6e 2f 76 6e 64 2e 77 61 70 2e 6d 6d 73 2d 6d 65 73 73 61 67 65  0 + WSP Header + MMS PDU(M-Retrieve.conf)

3.发送mms

发送 WSP PDU

WSP PDU Type: POST

MMSC uri: 

ContentType: application/vnd.wap.mms-message

HEX:60 19 24 + Ⅱ编码 + application/vnd.wap.mms-message 的ASCⅡ编码 + MMS PDU

 

发送 WTP PDU

WTP PDU Type: Invoke

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 3

Version: 0

TIDnew: 0

UACK: 1

TCL: 2

HEX:0a 00 03 12 + WSP PDU(POST)

 

接收的 WTP PDU

WTP PDU Type: Result

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 3

HEX:12 80 03 + WSP PDU(Reply)

 

发送 WTP PDU

WTP PDU Type: Acknowledgement

CON: 1

Tve/Tok: 0

RID: 0

TID: 3

TPI Type: PSN

CON: 0

Len: 1

PSN: 0

HEX:98 00 03 19 00

 

 

接收的 WSP PDU

WSP PDU Type: Reply

Status: 20

HeadersLen:0x33

ContentType:application/vnd.wap.mms-message

HEX:04 20 33 61 70 70 6c 69 63 61 74 69 6f 6e 2f 76 6e 64 2e 77 61 70 2e 6d 6d 73 2d 6d 65 73 73 61 67 65 00 + WSP Header + MMS PDU(M-Send.conf)

 

4.断开连接

发送 WSP PDU

WSP PDU Type: Disconnect

Server session id: bb 95 78

HEX:05 bb 95 78

 

发送 WTP PDU

WTP PDU Type: Invoke

CON: 0

GTR: 0

TTR: 1

RID: 0

TID: 4

Version: 0

TIDnew: 0

UACK: 0

TCL: 0

HEX: 0a 00 03 00 + WSP PDU(Disconnect)

 

 

转载地址:https://liwangjiang.blog.csdn.net/article/details/89205534 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android 通信Ril
下一篇:Android通知Notification合并问题App的消息通知超过3条时会合并到一起

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月06日 10时30分01秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章