支持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  =   " 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>   创建消息发送接口  
            MMSender   ms   =   new   MMSender();  
        2>   设置参数属性  
            默认属性已经是中国移动参数,因此如果是中国移动用户,以下两个操作可以不需要  
            ms.SetMMSC("
http://mmsc.monternet.com ");  
            ms.SetProxy("10.0.0.172:80");  
        3>   创建消息  
            MMessage   mm=   new   MMessage();  
        4>   设置消息内容  
            mm.SetSubject("标题");             //   设置标题  
            mm.AddTo("13810034500");         //   添加接收号码,调用一次添加一个接收号码  
            mm.AddFile("FileName");           //   添加发送文件,包含文件路径,调用一次添加一个发送文件  
        5>   发送消息  
              string   szReult   =ms.Send(mm);  
         
        6>   继续发送其他号码  
            mm.ClearTo();  
            mm.AddTo("13812345678");  
            ms.Send(mm);            
        
*/


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




        
public   string  Send(MMessage mm)
        {
            
try
            {
                
byte [] byMM  =  mm.MakeMMSContent();
                
if  (byMM.Length  >   50   *   1024 )
                    
return   " The package is too large! " ;
                
//    验证参数有效性  
                
// FileStream fs = new FileStream("d:/aaa.mms", FileMode.Create);
                
// fs.Write(byMM, 0, byMM.Length);
                
// fs.Close();
                
// return "OK";
                WebRequest wReq  =  WebRequest.Create(sMmscUrl);
                HttpWebRequest hReq 
=  (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.0   Series60/2.6   Profile/MIDP-2.0   Configuration/CLDC-1.1 " ;
                
//    Write   Post   Dat  
                
                hReq.ContentLength 
=  byMM.Length;
                Stream sReq 
=  wReq.GetRequestStream();
                sReq.Write(byMM, 
0 , byMM.Length);
                sReq.Close();
                WebResponse wRes 
=  wReq.GetResponse();
                HttpWebResponse hRes 
=  (HttpWebResponse)wRes;
                
if  (hRes.StatusCode  ==  HttpStatusCode.OK)
                {
                    Stream sRes 
=  wRes.GetResponseStream();
                    StreamReader sr 
=   new  StreamReader(sRes);
                    
string  szResult  =  sr.ReadToEnd();      //    发送结果  
                    sr.Close();
                    
return  szResult;
                }
            }
            
catch  (Exception e)
            {
                
throw   new  Exception(e.Message);
            }
            
return   string .Empty;
        }
    }
}

 

 

你可能感兴趣的:(支持smil文件的MMS PDU打包方式.)