支持smil文件的MMS PDU打包方式.
Posted axman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了支持smil文件的MMS PDU打包方式.相关的知识,希望对你有一定的参考价值。
mms如果不支持smil那就不能叫真正的MMS,mixed的格式对于多个附件的MMS来说不仅没有"排版"功能,
而且即使用你想一个文件一个文件"拆单了看",也不得不看一次手工播放一次,就象要手动"翻页".所以不支持
smil干脆就别玩MMS了.
但基于related格式的支持smil的PDU打包方式怎么也搜索不到,很多厂商和技术人员都故作神秘,不就是一
堆规范的实现吗?只好下了几个文档来研究,经过反复调试,其中用nowSMS的mmscomp打包出来的格式竟然
是错误的,最后多次抓包比较,总算成功了.在『别人原来的mixed方式』的基础上修改成related方式的.有需要的
就自己用去吧.(注意基础类是别人原来提供的,我只是提供了related方式的打包逻辑)
工程文件在:http://dl2.csdn.net/down4/20070706/06201955542.rar
using System;
using System.Net;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.Text;
/// <summary>
/// Lib 的摘要说明
/// </summary>
namespace MMSLib
public class MMessage
string subject = " 测试 " ;
int deliverTime = 0 ; // 多少秒以后开始投递
ArrayList inlineFiles = new ArrayList(); // 文件列表
ArrayList destinations = new ArrayList(); // 目标号码
static long serialNumber = 19700311L ; // 流水号
FileInfo smilFile;
public void SetSubject( string subject)
this .subject = subject;
public void SetDeliverTime( int deliverTime)
this .deliverTime = deliverTime;
//
public void AddTo( string dest)
destinations.Add(dest);
public void AddFile( string file)
if (file.ToLower().EndsWith( " .smil " ))
if ( this .smilFile != null )
throw new Exception( " The smil file has existed! " );
this .smilFile = new FileInfo(file);
inlineFiles.Add(file);
public void ClearTo()
destinations.Clear();
// 得到二进制编码字节
public byte [] MakeMMSContent()
if ( this .smilFile == null ) throw new Exception( " The smil file not found! " );
byte [] MMSContent = new byte [ 0 ];
// X-Mms-Message-Type
MMSContent = appendContent( new byte [] 0x8C , 0x80 , MMSContent);
// X-Mms-Transaction-ID
MMSContent = appendContent( new byte [] 0x98 , MMSContent);
MMSContent = appendContent(serialNumber.ToString(), MMSContent);
serialNumber ++ ;
MMSContent = appendContent( new byte [] 0x0 , MMSContent);
// X-Mms-MMS-Version
MMSContent = appendContent( new byte [] 0x8D , 0x90 , MMSContent);
// Date
MMSContent = appendContent( new byte [] 0x85 , MMSContent);
TimeSpan ts = DateTime.Now - new DateTime( 1970 , 1 , 1 , 0 , 0 , 0 );
int sec = ( int )ts.TotalSeconds;
byte [] bySec = BitConverter.GetBytes(sec);
MMSContent = appendContent( new byte [] ( byte )bySec.Length , MMSContent);
Array.Reverse(bySec);
MMSContent = appendContent(bySec, MMSContent);
if (deliverTime > 0 )
MMSContent = appendContent( new byte [] 0x87 , MMSContent);
byte [] bfTime = BitConverter.GetBytes(deliverTime);
Array.Reverse(bfTime);
byte [] bfTimeLen = new byte [ 3 ];
bfTimeLen[ 0 ] = ( byte )(bfTime.Length + 2 );
bfTimeLen[ 1 ] = 0x81 ; // 相对时间格式
bfTimeLen[ 2 ] = ( byte )bfTime.Length;
MMSContent = appendContent(bfTimeLen, MMSContent);
MMSContent = appendContent(bfTime, MMSContent);
// From,Len = 0x01,一个以0x81为标记的占位符,发送时自动插入发送号码.
MMSContent = appendContent( new byte [] 0x89 , 0x01 , 0x81 , MMSContent);
// To
for ( int i = 0 ; i < destinations.Count; i ++ )
MMSContent = appendContent( new byte [] 0x97 , MMSContent);
MMSContent = appendContent( " +86 " + ( string )destinations[i] + " /TYPE=PLMN " , MMSContent);
// MMSContent = appendContent(new byte[] 0x20, 0x20, 0x0 , MMSContent);
MMSContent = appendContent( new byte [] 0x0 , MMSContent);
// subject
if (subject.Length > 0 ) // 使用Utf8编码
MMSContent = appendContent( new byte [] 0x96 , MMSContent);
byte [] byLen = new byte [ 1 ];
byLen[ 0 ] = ( byte )(Encoding.UTF8.GetByteCount(subject) + 2 );
MMSContent = appendContent(byLen, MMSContent);
MMSContent = appendContent( new byte [] 0xEA , MMSContent);
MMSContent = appendContent(Encoding.UTF8.GetBytes(subject), MMSContent);
MMSContent = appendContent( new byte [] 0x0 , MMSContent);
MMSContent = appendContent( new byte [] 0x84 , MMSContent);
int ctLen = 2 // 0xB3 ,0x89
+ " application/smil " .Length
+ 3 // 0x00 0x8A 0x3c
+ smilFile.Name.Length
+ 2 ; // 0x3c,0x00
byte [] cl = uintToBytes(ctLen);
if (cl[ 0 ] >= 0x1F )
MMSContent = appendContent( new byte [] 0x1F , MMSContent);
MMSContent = appendContent(cl, MMSContent);
MMSContent = appendContent( new byte [] 0xB3 , MMSContent);
// 0xB3 Content-Type:application/vnd.wap.multipart.related
MMSContent = appendContent( new byte [] 0x89 , MMSContent);
MMSContent = appendContent(Encoding.ASCII.GetBytes( " application/smil " ), MMSContent);
MMSContent = appendContent( new byte [] 0x0 , MMSContent);
MMSContent = appendContent( new byte [] 0x8A , 0x3C , MMSContent); // 0x8A:Start,0x3C:<
MMSContent = appendContent(Encoding.ASCII.GetBytes( smilFile.Name ), MMSContent);
MMSContent = appendContent( new byte [] 0x3E , 0x0 , MMSContent); // 0x3E:>
byte [] byFileCount = new byte [ 1 ];
byFileCount[ 0 ] = ( byte )inlineFiles.Count;
MMSContent = appendContent(byFileCount, MMSContent);
int chLen = " application/smil " .Length
+ 4 // 0x00 0xc0 0x22 0x3c: cid,",<
+ smilFile.Name.Length
+ 3 // 0x3E,0x00,0x8E
+ smilFile.Name.Length
+ 1 ; // 0x00
for ( int j = 0 ; j < inlineFiles.Count; j ++ )
MMSContent = appendContent(GetFileContent(inlineFiles[j].ToString()), MMSContent);
return MMSContent;
// 打包文件
private byte [] GetFileContent( string FileName)
byte [] byHeaders = new byte [ 0 ]; // ContentType和Headers组合
byte [] byData = readFile(FileName);
string FileID = getContentId(FileName);
if (FileName.EndsWith( " .txt " ))
byHeaders = new byte [ 1 ];
byHeaders[ 0 ] = ( byte )(Encoding.ASCII.GetByteCount(FileID) + 5 );
byHeaders = appendContent( new byte [] 0x83 , 0x85 , byHeaders); // Utf-8
byHeaders = appendContent(Encoding.ASCII.GetBytes(FileID), byHeaders);
byHeaders = appendContent( new byte [] 0x00 , byHeaders);
byHeaders = appendContent( new byte [] 0x81 , 0xEA , byHeaders);
else if (FileName.EndsWith( " .gif " ))
byHeaders = new byte [] 0x9D ;
else if (FileName.EndsWith( " .mid " ) || FileName.EndsWith( " .midi " ))
byHeaders = Encoding.ASCII.GetBytes( " audio/midi " );
byHeaders = appendContent( new byte [] 0x00 , byHeaders);
else if (FileName.EndsWith( " .smil " ))
byHeaders = Encoding.ASCII.GetBytes( " application/smil " );
byHeaders = appendContent( new byte [] 0x00 , byHeaders);
// 加入Content-ID
byHeaders = appendContent( new byte [] 0xC0 , 0x22 , 0x3C , byHeaders);
byHeaders = appendContent(Encoding.ASCII.GetBytes(FileID), byHeaders);
byHeaders = appendContent( new byte [] 0x3E , 0x00 , byHeaders);
// 加入Content-Location
byHeaders = appendContent( new byte [] 0x8E , byHeaders);
byHeaders = appendContent(Encoding.ASCII.GetBytes(FileID), byHeaders);
byHeaders = appendContent( new byte [] 0x00 , byHeaders);
byte [] byHeaderLen = uintToBytes(byHeaders.Length);
byte [] byDataLen = uintToBytes(byData.Length);
byte [] byMmc = new byte [byHeaderLen.Length + byDataLen.Length + byHeaders.Length + byData.Length];
Array.Copy(byHeaderLen, byMmc, byHeaderLen.Length);
Array.Copy(byDataLen, 0 , byMmc, byHeaderLen.Length, byDataLen.Length);
Array.Copy(byHeaders, 0 , byMmc, byHeaderLen.Length + byDataLen.Length, byHeaders.Length);
Array.Copy(byData, 0 , byMmc, byHeaderLen.Length + byDataLen.Length + byHeaders.Length, byData.Length);
return byMmc;
private byte [] uintToBytes( int n)
byte [] buf = new byte [ 8 ];
int l = 0 ;
while (n >= 128 )
byte b = ( byte )(n & 0x7F );
n = n >> 7 ;
buf[l ++ ] = b;
buf[l ++ ] = ( byte )n;
byte [] retBys = new byte [l];
for ( int i = 0 ; i < l; ++ i)
retBys[i] = ( byte )(buf[l - i - 1 ] | 0x80 );
retBys[l - 1 ] &= 0x7F ;
return retBys;
// 读取文件
private byte [] readFile( string FileName)
if (FileName.EndsWith( " .txt " ))
StreamReader sr = null ;
try
sr = new StreamReader(FileName, Encoding.Default);
string text = sr.ReadToEnd();
byte [] bf = Encoding.UTF8.GetBytes(text);
return bf;
catch
return new byte [ 0 ];
finally
if (sr != null ) sr.Close();
FileStream fs = null ;
try
fs = new FileStream(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); // 没有设定Buffsize
byte [] bf = new byte [fs.Length];
fs.Read(bf, 0 , ( int )fs.Length);
return bf;
catch
return new byte [ 0 ];
finally
if (fs != null ) fs.Close();
private string getContentId( string FileName)
int at = FileName.LastIndexOf( " / " );
if (at < 0 )
at = FileName.LastIndexOf( " / " );
return FileName.Substring(at + 1 );
private byte [] appendContent( byte [] srcBys, byte [] destBys)
Array.Resize( ref destBys, srcBys.Length + destBys.Length);
Array.Copy(srcBys, 0 ,destBys,destBys.Length - srcBys.Length,srcBys.Length);
return destBys;
private byte [] appendContent( string sz, byte [] byDest)
return appendContent(Encoding.Default.GetBytes(sz), byDest);
/// <summary>
/// MMSender 的摘要说明。
///
/// </summary>
public class MMSender
// 设置参数
string sMmscUrl = "
以上是关于支持smil文件的MMS PDU打包方式.的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式通过 ios 7+ 中的 mms 发送图像? [关闭]
急求基于Java的smil文件解析器,我把的全部积分送出去,谢啦