彩信MMS PDU 的解码

本文深入探讨了MMS消息系统的工作原理及MMSPDU编码规则,重点介绍了MM1接口上MMSPDU的具体格式及其解码过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      前一时间折腾了一下手机方面的开发,用的是NOKIA智能手机,NOKIA网站有一个很方便的开发包Nokia_PC_Connectivity_API_3.2。

这个开发包带有VB.NET,C#,VC的文件系统,设备管理,内容存取的开发例子。试了试可以正常收发短信,但彩信只可以看到条目标题,时间,看不了内容,了解一下,在Content Access API 3.2里的CA_MMS_DATA。这个结构体中,重要的BYTE* pbData 没有相关说明,例子里也没有解析。

      这几天把手机的pbData数据异了一些出来,网上查了一下,发现是彩信的PDU编码格式就到网上找了一下,相关开发入门的例子和协议,竟发现不好找。乱七八糟的。说什么的都有。因为自已的手机码是使用移动的就找了一下关于移动的相关文件,很快就找到《中国移动多媒体消息系统(MMS)接口规范》。了解一下整个MMS流程。

 

多媒体消息业务涉及的系统接口

整个MMS业务环境通过WAP网关与移动网相连,各接口协议都是HTTP或SMTP等通用的Internet协议。其中: 
   MM1:MMS用户代理(MMS手机上的应用程序,如浏览器)和MMS代理/服务器(MMSC)之间的参考点,基于WAP和HTTP实现;
   MM2:MMS中继和MMS服务器之间的参考点,一般是MMSC内部的接口;
   MM3:MMS服务中心和外部消息系统间的参考点,基于IP实现,如与Email服务器相连,则采用SMTP协议;
   MM4:MMS服务中心和另一个MMSE中的MMS服务中心间的参考点,基于SMTP实现;
   MM5:MMS服务中心和HLR间的参考点,非必须;
   MM6:MMS服务中心和MMS用户数据库间的参考点,可以是内部接口或外部接口;
   MM7:MMS服务中心和MMS增值业务应用之间的参考点,基于IP实现;
   MM8:MMS服务中心和计费系统间的参考点。

 

看了一下,再加之前面找的一些乱七八糟的资料,了解到开发彩信有两个种要的开发接口,一个是MM1接口,和MM7接口。

MM1是以终端设备方式(手机终端、GPRS modem),MM7是以SP增值业务方式接入.

说明自已手机异出的数据是MM1接口的协议上的mms pdu数据。

 

MMS PDU 的解码

 

    MMS PDU 的具体编码规则在:WAP-209-MMSEncapsulation-20020105-a.pdf或在OMA-MMS-ENC-V1_2-20050301-A.pdf上有介绍。

   MMS PDU被封装在WSP/PDU之中 作为WSP的消息体进行传输,并采用WAP/WSP协议作为传输内容的二进制编码(binary encoding)机制,进行消息的封装(Encapsulation)。
在OMA-TS-MMS-ENC-V1_3-20080128-C.pdf文档所在规范中,详细定义了每个PDU所涉及的Header域和值,以及为它们分配的二进制码的一一对应关系。采用此二进制编码规范,节约了无线领域的带宽资源,并最优化其在空中传播的数据量。
具体对应关系请参阅相关文档。
MMS 编码必须遵循无线会话协议( Wireless Session Protocol,以下简称 WSP)。
WSP使用一种与 HTTP/1.1相同的语法描述数据的组织结构,具体可参考 RFC[2068]。
HTTP/1.1使用 ASCII字符编码来传输数据,而 WSP为降低传输带宽,将 HTTP/1.1中的一些著名域对应的字符串定义为一个字节,并在对这些紧凑格式编码时加上 0x80,使著名域的编码大于 127(扩展 ASCII字符),从而将它们与普通 ASCII字符区别开。因此 MMS信息头的基本编码格式为:“域编码”+“内容”,详情请参考表 1。编码顺序如下:消息类型、事务 ID、版本号必须依次排在最前面,而 MMS信息体内容类型则应该排在 MMS信息头的最后。

 

MMS PDU头域分析和头域编码
    每个MMS PDU都是由MMS头域和MMS消息体组成,MMS PDU中的头域由客户端指定,一些头域也可以被分发代理修改或补充,分发代理使用这些头域信息生成MM通知以及构造接收MM的PDU中的相关头域,连同消息实体一同送往接收方,消息体跟在头域之后。大多数MMS PDU只含有头域,它们起到建立和维持通信的作用,消息体只用在M-Send.req和M-Retrieve.conf PDU中。
    MMS头域根据WAP-209协议和RFC2387的规定,由一系列的域组成,这些域定义了PDU的各种属性,包括PDU类型,接受方,发送方,发送时间等,头域中的域名分为可选项和必选项。在编码MMS头域时,X-Mms-Message-Type ,X-Mms-Transaction-ID和X-Mms-MMS-Version必须位于MMS头的开始,并且按照前面所列的顺序。Content-Type必须在MMS头域的最后,其后为消息体,其它域的顺序可以随意安排。

 

参考表 1

Name Assigned Number 
Bcc 0x01 
Cc 0x02 
X-Mms-Content-Location 0x03 
Content-Type 0x04 
Date 0x05 
X-Mms-Delivery-Report 0x06 
X-Mms-Delivery-Time 0x07 
X-Mms-Expiry 0x08 
From 0x09 
X-Mms-Message-Class 0x0A 
Message-ID 0x0B 
X-Mms-Message-Type 0x0C 
X-Mms-MMS-Version 0x0D 
X-Mms-Message-Size 0x0E 
X-Mms-Priority 0x0F 
X-Mms-Read-Report 0x10 
X-Mms-Report-Allowed 0x11 
X-Mms-Response-Status 0x12 
X-Mms-Response-Text 0x13 
X-Mms-Sender-Visibility 0x14 
X-Mms-Status 0x15 
Subject 0x16 
To 0x17 
X-Mms-Transaction-Id 0x18 
X-Mms-Retrieve-Status 0x19 
X-Mms-Retrieve-Text 0x1A 
X-Mms-Read-Status 0x1B 
X-Mms-Reply-Charging 0x1C 
X-Mms-Reply-Charging-Deadline 0x1D 
X-Mms-Reply-Charging-ID 0x1E 
X-Mms-Reply-Charging-Size 0x1F 
X-Mms-Previously-Sent-By 0x20 
X-Mms-Previously-Sent-Date 0x21 
X-Mms-Store 0x22 
X-Mms-MM-State 0x23 
X-Mms-MM-Flags 0x24 
X-Mms-Store-Status 0x25 
X-Mms-Store-Status-Text 0x26 
X-Mms-Stored 0x27 
X-Mms-Attributes 0x28 
X-Mms-Totals 0x29 
X-Mms-Mbox-Totals 0x2A 
X-Mms-Quotas 0x2B 
X-Mms-Mbox-Quotas 0x2C 
X-Mms-Message-Count 0x2D 
Content 0x2E 
X-Mms-Start 0x2F 
Additional-headers 0x30 
X-Mms-Distribution-Indicator 0x31 
X-Mms-Element-Descriptor 0x32 
X-Mms-Limit 0x33 

 

 

如HEX数据:8C 80 8D 90 85 04 4CA72474
8C—表示X-Mms-Message-Type
80— m-send-req
8D— X-Mms-Version
90— MMS Version值1.0
85— 表示date
04— 表示date的数据长度
4CA72474 -表示date的数据Little-endian,从1970年开始到现在的秒数
96—subject主题
89— 表示From
97— 表示From
From=0x89+长度+ 0x80+地址+0x00(收到时解码用) 还有发送时用的格式:0x89, 0x01, 0x81 以0x81为标记的占位符,发送时自动插入发送号码From=0x97+内容+0x00
CC =0x82+号码+0x00
subject=0x98+长度+字符集+字符串+0x00;//(常为用Utf8长度+2)+0xEA+内容+0x00
...
以上分析的就是一个典型的MMS PDU消息格式,按上面参考表 1配合WAP-209文档说明,很轻松的就解码了

<think>嗯,用户想用Python实现彩信MMS PDU编码的示例代码。首先,我需要回忆一下MMS PDU的结构。根据引用[1],MMS PDU由消息和消息体组成,大部分只有Header,只有M-Send.req和M-Retrieve.conf包含Body。那用户的需求是生成这样的PDU,可能需要构造Header和可能的Body部分。 接下来,我得考虑MMS的协议规范,比如3GPP TS 23.140,但用户可能需要的是具体的Python实现步骤。可能需要参考现有的实现方式或者库,不过用户要的是示例代码,所以可能需要手动构建字节流。 首先,构造PDU的Header部分。比如,M-Send.req需要事务ID、版本、消息类型、From、To、内容类型等字段。这些字段需要按照MMS的编码规范转换成二进制格式。例如,事务ID可能是一个字符串,需要编码为长度后跟字符的字节。版本可能是0x92表示MMS 1.2。消息类型对应的值,比如M-Send.req是0x80。 然后是Content-Type,比如彩信通常使用application/vnd.wap.multipart.related,需要编码为参数和值。这部分可能需要使用WSP(Wireless Session Protocol)的编码方式,比如使用Content-Type的常量值,或者进行二进制编码。 另外,用户提到引用[3]中的Android处理彩信的部分,可能涉及到PDU的解析和发送,但用户需要的是生成PDU,所以可能需要构造类似的二进制数据,但用Python实现。 考虑到Python处理字节流,可能需要使用struct模块来打包二进制数据,或者手动拼接字节。例如,每个字段可能有一个标识符,后面跟着长度和值。比如,X-Mms-Message-Type字段的值是0x80,可能需要用特定的字节表示。 另外,彩信的内容部分可能需要构造multipart结构,比如使用SMIL来描述布局,以及各个部分(如图片、文本)作为附件。这部分需要生成multipart的boundary,并正确设置各部分的内容类型和内容ID。 可能还需要处理地址编码,比如将电话号码编码成特定的格式,如用TON和NPI指定类型,比如国际号码的TON是0x91,号码是字符串形式的字节。 示例代码可能需要分步骤,先构造Header部分,再处理Body部分。对于Body,可能需要生成multipart的各个部分,并将整个内容作为二进制数据附加到PDU中。 需要注意的是,MMS编码比较复杂,用户可能需要简化示例,只展示关键部分,比如构造一个基本的M-Send.req PDU,包含必要的Header字段和一个简单的文本部分。 此外,用户的问题中提到引用[2]中的数据库表,可能与存储彩信有关,但当前任务可能不涉及数据库操作,所以可以暂时忽略。 最后,可能需要提醒用户实际应用中需要考虑更多细节,如编码方式、不同版本的支持、错误处理等,并建议参考官方文档或现有库。</think>根据MMS协议规范[^1],MMS PDU编码需要遵循WAP/WSP协议格式。以下是用Python实现彩信PDU编码的示例框架: ```python from binascii import unhexlify def encode_mms_pdu(to_addr, subject, content): # 基础部构造 header = b"" header += b"\x8c\x80" # X-Mms-Message-Type: m-send-req (0x80) header += b"\x8d\x92" # X-Mms-Version: 1.2 (0x92) # 目标地址编码 to_addr_enc = encode_address(to_addr) header += b"\x97" + bytes([len(to_addr_enc)]) + to_addr_enc # 主题编码 subject_enc = encode_string(subject) header += b"\x96" + bytes([len(subject_enc)]) + subject_enc # 内容类型(application/vnd.wap.multipart.related) content_type = b"\x03\x2e\x01\x84\xb5\x01" # OMA-TS-MMS_ENC-V1_2-20040726-A header += b"\x84" + bytes([len(content_type)]) + content_type # 消息体构造 body = encode_multipart(content) return header + body def encode_address(addr): # 地址类型编码(TON/NPI) return unhexlify("81") + addr.encode("ascii") def encode_string(s): # 文本编码(默认UTF-8) return s.encode("utf-8") def encode_multipart(content): # 构造multipart消息体 boundary = b"--=boundary" parts = [ b"Content-Type: text/plain\r\n\r\n" + content.encode("utf-8"), # 可添加更多附件部分 ] return boundary.join(parts) + boundary + b"--\r\n" ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值