彩信協議相比於上一篇白話短信協議會稍微複雜一些git
和介紹短信協議時同樣,咱們先簡單介紹一下手機收到彩信的過程,實際上手機收到彩信有兩個步驟,第一步會接收到彩信通知,第二步會去彩信通知中給的地址下載彩信文件github
以上第一步和咱們普通文本短信同樣是是以短信協議的方式發送到手機上(wap-push),第二步則是經過通知中附帶的地址去下載彩信文件(wap-wsp)segmentfault
一樣,接下來經過白話的方式向你解釋這個協議app
第一步既然也是短信協議,咱們先回顧一下短信協議的組成,是這個樣子的:less
包含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是這樣的:spa
2948的16進製爲0x0B84
,9200的16進製爲0x23F0
,因此最後UDH就是:0x05 0x04 0x0B 0x84 0x23 0xF0
code
接着咱們再來講UD,咱們前面提到了,咱們通知中會帶上彩信文件的地址,當手機收到通知時,會去該地址下載彩信文件,因此,彩信的地址必然在咱們UD中,哪還有哪些東西須要包含在UD中呢?視頻
不知道你們有沒有注意過彩信在手機中展現是什麼樣的呢?彩信確定會有圖片、視頻這些主要信息,不過還會發送人、主題、彩信大小這些信息。那在咱們通知中須要包含上面哪些信息呢,實際上以上就是咱們彩信文件所包含的所有信息,不過通知中是不須要圖片、視頻這些主要信息的,否則還要通知幹什麼呢,那剩下的就是通知中須要帶上的信息了,包括髮送人、主題、彩信大小。blog
好了,咱們知道了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剩下的部分也知道了,就是這個樣子:
這裏大多數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)縮短了
最後,咱們從協議的層面來看下通知是什麼樣子的:
前面咱們說通知的時候提到了,彩信文件其實就是比彩信通知多了圖片、視頻的信息,從協議來看就是比彩信通知(信息部分MMSEP header)多了信息體,其實信息體裏就是放的圖片、視頻,彩信文件就是這個樣子:
前面咱們已經介紹過了MMSEP header,那咱們彩信文件裏只是部分header的值不一樣,其它都與通知時同樣的,下面我把不一樣的取值給你列出來
content_type: application/vnd.wap.multipart.related
或application/vnd.wap.multipart.mixed
message_type: 以前也提到過,若是是彩信文件message_type=4
date: 表示彩信生成時間,不一樣於通知的expiry,彩信文件中是date
這裏就不例出彩信文件的編碼結果了,內容和通知中MMSEP header部分類似,只是多了圖片、視頻的編碼(固然一樣包含其content_type);包括咱們以前提到編碼方式的地方,都只是簡單說明或直接給的值,沒有說具體的方式,由於WSP編碼仍是比較複雜的,有興趣能夠到SMSJ查看
smsj是個短彩信協議項目、有完整豐富的doc,smsj能方便的生成短彩信協議內容,具體使用方式能夠查看項目地址