支持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 ; // 多少秒以后开始投递
ArrayListinlineFiles = new ArrayList(); // 文件列表
ArrayListdestinations = new ArrayList(); // 目标号码

static long serialNumber = 19700311L ; // 流水号
FileInfosmilFile;



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( " Thesmilfilehasexisted! " );
this .smilFile = new FileInfo(file);
}
inlineFiles.Add(file);
}

public void ClearTo()
{
destinations.Clear();
}

// 得到二进制编码字节
public byte []MakeMMSContent()
{

if ( this .smilFile == null ) throw new Exception( " Thesmilfilenotfound! " );

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);
TimeSpants
= 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(newbyte[]{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 // 0x000x8A0x3c
+ 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);
// 0xB3Content-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 // 0x000xc00x220x3c: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 " )){

StreamReadersr
= 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();
}
}
FileStreamfs
= 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 = " http://mmsc.monternet.com " ;
string sProxyUrl = " 10.0.0.172:80 " ;

public MMSender()
{
//
// TODO:在此处添加构造函数逻辑
//
}
public void SetMMSC( string szUrl)
{
sMmscUrl
= szUrl;
}
public void SetProxy( string szUrl)
{
sProxyUrl
= szUrl;
}


/* 发送MMS的过程
1>创建消息发送接口
MMSenderms=newMMSender();
2>设置参数属性
默认属性已经是中国移动参数,因此如果是中国移动用户,以下两个操作可以不需要
ms.SetMMSC("
http://mmsc.monternet.com ");
ms.SetProxy("10.0.0.172:80");
3>创建消息
MMessagemm=newMMessage();
4>设置消息内容
mm.SetSubject("标题");//设置标题
mm.AddTo("13810034500");//添加接收号码,调用一次添加一个接收号码
mm.AddFile("FileName");//添加发送文件,包含文件路径,调用一次添加一个发送文件
5>发送消息
stringszReult=ms.Send(mm);

6>继续发送其他号码
mm.ClearTo();
mm.AddTo("13812345678");
ms.Send(mm);
*/


/* 避免协议冲突的设置
<configuration>
<system.net>
<settings>
<httpWebRequestuseUnsafeHeaderParsing="true"/>
</settings>
</system.net>
</configuration>
*/




public string Send(MMessagemm)
{
try
{
byte []byMM = mm.MakeMMSContent();
if (byMM.Length > 50 * 1024 )
return " Thepackageistoolarge! " ;
// 验证参数有效性
// FileStreamfs=newFileStream("d:/aaa.mms",FileMode.Create);
// fs.Write(byMM,0,byMM.Length);
// fs.Close();
// return"OK";
WebRequestwReq = WebRequest.Create(sMmscUrl);
HttpWebRequesthReq
= (HttpWebRequest)wReq;
wReq.Headers.Clear();
if (sProxyUrl.Length > 0 )
wReq.Proxy
= new WebProxy(sProxyUrl);

wReq.ContentType
= " application/vnd.wap.mms-message " ;
hReq.Accept
= " application/vnd.wap.mms-message,text/plain,*/* " ;
wReq.Method
= " POST " ;
hReq.KeepAlive
= false ;
hReq.UserAgent
= " Nokia6681/2.0(4.00.15)SymbianOS/8.0Series60/2.6Profile/MIDP-2.0Configuration/CLDC-1.1 " ;
// WritePostDat

hReq.ContentLength
= byMM.Length;
StreamsReq
= wReq.GetRequestStream();
sReq.Write(byMM,
0 ,byMM.Length);
sReq.Close();
WebResponsewRes
= wReq.GetResponse();
HttpWebResponsehRes
= (HttpWebResponse)wRes;
if (hRes.StatusCode == HttpStatusCode.OK)
{
StreamsRes
= wRes.GetResponseStream();
StreamReadersr
= new StreamReader(sRes);
string szResult = sr.ReadToEnd(); // 发送结果
sr.Close();
return szResult;
}
}
catch (Exceptione)
{
throw new Exception(e.Message);
}
return string .Empty;
}
}
}

你可能感兴趣的:(.net,J#,中国移动,WAP)