白话彩信协议

白话彩信协议

彩信协议相比于上一篇白话短信协议会稍微复杂一些

和介绍短信协议时一样,我们先简单介绍一下手机收到彩信的过程,实际上手机收到彩信有两个步骤,第一步会接收到彩信通知,第二步会去彩信通知中给的地址下载彩信文件

以上第一步和我们普通文本短信一样是是以短信协议的方式发送到手机上(wap-push),第二步则是通过通知中附带的地址去下载彩信文件(wap-wsp)

同样,接下来通过白话的方式向你解释这个协议

通知

第一步既然也是短信协议,我们先回顾一下短信协议的组成,是这个样子的:

包含UDH和UD,那彩信通知中UDH和UD的值是什么呢?

先说UDH,其包含2个端口信息(wap-push:2948,wap-wsp:9200),这两个端口是IANA注册的端口,我们后面说,现在我们只需要知道,要存下这两个端口需要4个字节(每个端口2字节),我们正好有IEI为0x05(Application port addressing scheme, 16 bit address),表示IED包含的是16位的端口信息,那我们通知的UDH是这样的:

mms-udh.png

2948的16进制为0x0B84,9200的16进制为0x23F0,所以最后UDH就是:0x05 0x04 0x0B 0x84 0x23 0xF0

接着我们再来说UD,我们前面提到了,我们通知中会带上彩信文件的地址,当手机收到通知时,会去该地址下载彩信文件,所以,彩信的地址必然在我们UD中,哪还有哪些东西需要包含在UD中呢?

不知道大家有没有注意过彩信在手机中展示是什么样的呢?彩信肯定会有图片、视频这些主要信息,不过还会发送人、主题、彩信大小这些信息。那在我们通知中需要包含上面哪些信息呢,实际上以上就是我们彩信文件所包含的全部信息,不过通知中是不需要图片、视频这些主要信息的,不然还要通知干什么呢,那剩下的就是通知中需要带上的信息了,包括发送人、主题、彩信大小。

好了,我们知道了UD中需要存哪些信息,接下来,我们就来看下UD的具体组成

老规矩,在这之前,介绍个概念

WSP(Wireless Session Protocol): 这是一种基于HTTP1.1的一种协议,有自己的编码方式

我们前面说UDH的时候提到,有2个端口信息(wap-push, wap-wsp),这俩个端口恰好对应我们彩信的两个过程,可以把它们当做目的地和源地,我们UD也正是用WSP编码方式存储的,这里简单的说一下WSP是怎么编码的

WSP编码其实可以看做key-value编码,key的编码又有2种,一种可以当做是内置的key,一种是自定义的key

内置key的有对应的一个字节内容代表,自定义key会用专门的字符串编码方式进行编码,value和自定义key一样,如果是字符串会用专门的字符串编码方式进行编码,数字则会用专门的数字编码方式进行编码

我们UD组成也包含信息头和信息体,这个信息头和信息体就不是短信中的UDH和UD了,而是WSP的信息头和信息体

信息头

WSP信息头很简单,包含一个TID和一个PDU TYPE,各占一个字节,TID不用去关心它,我们只需要关心当pdu_type=6时,就表示这是一个wap-push就OK了

比如,我们假设TID=0那么WSP头就为:0x00 0x06

信息体

这里我们再介绍一个概念

MMSEP(Multimedia Messaging Service Encapsulation Protocol): 彩信封装协议,是基于WSP协议

MMSEP也包含信息头和信息体,还记得我们之前说通知和彩信文件的内容差不多吗?其实彩信文件和通知相同的部分就是MMSEP的信息头,多出来的图片、视频就是MMSEP的信息体了,其实通知就是一个信息体为空的MMSEP

MMSEP信息头会指定一个content_type,content_type也是根据专门的字符串编码方式进行编码,比如彩信通知的content_type为:application/vnd.wap.mms-message,MMSEP的content_type和普通content_type不太一样,MMSEP的content_type能带参数,并一起参与编码,彩信通知的content_type就带有一个参数X-Wap-Application-ID=x-wap-application:mms.ua

这里我们简单看一下content_type结果:0x22 0x61 ... 0x00 0xAF 0x84

我们大概解释一下这串编码,还记得前面说的WSP编码方式吗?X-Wap-Application-ID这个key是内置的,用0xAF表示,x-wap-application:mms.ua同样,用0x84表示,那再来看前面的,因为application/vnd.wap.mms-message不是内置的key,所以得按照特殊字符串编码方式编码,第一位表示长度0x22,后面0x61 ... 0x00 就是编码内容了(这里就省略了)

我们接着看,MMSEP信息头里面除了我们之前提到的发送人、主题、彩信大小外,还会有一些其它信息,我们挨个介绍一下

version: 表示使用的WSP编码版本

message_type: 表示彩信类型

transaction_id: 表示事物ID

message_class_id: 表示彩信分类ID

expiry: 表示彩信有效期

subject: 表示标题

location: 表示彩信文件地址(我们前面提到,WSP是基于HTTP的协议,这里可以是一个HTTP地址)

from: 表示发送人

这里我们特别解释一下message_type,message_type代表了这个是一种什么类型的彩信,比如message_type=2表示这是一个通知,message_type=4表示这是一个彩信文件

那到这里,我们的通知UD剩下的部分也知道了,就是这个样子:

MMSEP-header.png

这里大多数key都是内置的,我举几个例子,比如

0x8D90 0x80表示这是version,0x90表示值为1.0;

0x8A80表示msg_class_id=personal;

0x8C82表示message_type=2;

0x98表示transaction_id,0x88 表示expiry,0x89表示from,0x8E表示size,0x83表示location,0x96表示subject;

这里没有例出的值的key,它们的值就需要用特殊的字符串或者数字编码了

到这里,我们通知的部分就介绍完了,整个通知大概就是:0x05 0x04 0x0B 0x84 0x23 0xF0 0x00 0x06 0x22 0x61 ... 0x00 0xAF 0x84 0x8D90 0x8A80 0x8C82 0x98 ... 0x88 ... 0x89 ... 0x8E ... 0x83 ... 0x96 ...

这里补充一点,可能你也注意到了,从最终结果来看,既然我们彩信通知和普通文本短信一样,而且我们编码出来的东西很可能超过了短信字节的限制,那同样也会有可能出现一个通知分为多条发送的情况,这种情况下,我们不能省略必要的信息,能做的可能就是将location(uri)缩短了

最后,我们从协议的层面来看下通知是什么样子的:

notification-msg.png

彩信文件

前面我们说通知的时候提到了,彩信文件其实就是比彩信通知多了图片、视频的信息,从协议来看就是比彩信通知(信息部分MMSEP header)多了信息体,其实信息体里就是放的图片、视频,彩信文件就是这个样子:

mms.png

前面我们已经介绍过了MMSEP header,那我们彩信文件里只是部分header的值不同,其它都与通知时一样的,下面我把不同的取值给你列出来

content_type: application/vnd.wap.multipart.relatedapplication/vnd.wap.multipart.mixed

message_type: 之前也提到过,如果是彩信文件message_type=4

date: 表示彩信生成时间,不同于通知的expiry,彩信文件中是date

这里就不例出彩信文件的编码结果了,内容和通知中MMSEP header部分相似,只是多了图片、视频的编码(当然同样包含其content_type);包括我们之前提到编码方式的地方,都只是简单说明或直接给的值,没有说具体的方式,因为WSP编码还是比较复杂的,有兴趣可以到SMSJ查看

SMSJ

smsj是个短彩信协议项目、有完整丰富的doc,smsj能方便的生成短彩信协议内容,具体使用方式可以查看项目地址

下一篇白话CMPP、SGIP
阅读 1.3k

推荐阅读
iven_wong的专栏
用户专栏

2 人关注
4 篇文章
专栏主页