关闭

中国移动短信网关CMPP3.0 C#源代码:数据包定义

2544人阅读 评论(1) 收藏 举报

关于联合
CMPP定义的各种数据包采用C语言中的联合(Union)来处理是最有效率的,因为接收和发送的是一个字节数组,使用联合可以方便地在字节数组和数据包结构之间转换。C#本身并不支持联合,但可以使用P/Invoke(平台封送调用)机制实现类似于联合的结构。
在定义CMPP数据包时,我为每个数据包结构定义了Init函数(用于将字节数组转换为数据包结构)和GetBuffer函数(用于将数据包结构转换为字节数组),主要是因为当时对P/Invoke机制不太熟悉。
使用Init和GetBuffer函数的结果是效率要比使用联合低很多,不过压力测试的时候系统表现还是相当稳定的。有兴趣的朋友可以试试用联合实现CMPP的数据包。

using System;
using System.Runtime.InteropServices;

namespace Tiray.SMS
{
 public struct DATA_PACKAGE
 {
  public UInt32 Command;
  public UInt32 SequenceID;//流水号
  public object Data;//数据
  public DateTime SendTime; //数据包发送时间
  public int SendCount;//发送次数
  public int Status;//数据包状态 0--空,1--待发送,2--已发送
 }
 
 #region Enums
 public enum SMS_STATE
 {
  SP_CONNECT,ACTIVE_TEST,ACTIVE_TEST_RESPONSE,SUBMIT,SUBMIT_RESPONSE,DELIVER,DELIVER_RESPONSE,REPORT,SP_DISCONNECT,
  SP_CONNECT_ERROR,ACTIVE_TEST_ERROR,ACTIVE_TEST_RESPONSE_ERROR,SUBMIT_ERROR,SUBMIT_RESPONSE_ERROR,DELIVER_ERROR,DELIVER_RESPONSE_ERROR,SP_DISCONNECT_ERROR,UNKNOW_ERROR

 }

 public enum CODING
 {
  ASCII=0,BINARY=4,UCS2=8,GBK=15
 }
 #endregion

 #region CMPP30 Data Packages
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_HEAD
 {
  public UInt32   TotalLength;
  public UInt32   CommandID;
  public UInt32   SequenceID;
  public Byte[] GetBuffer()
  {
   Byte[] buffer=new Byte[Marshal.SizeOf(this)];//12;
   Byte[] temp=null;
   temp=BitConverter.GetBytes(TotalLength);
   buffer[3]=temp[0];
   buffer[2]=temp[1];
   buffer[1]=temp[2];
   buffer[0]=temp[3];
   temp=BitConverter.GetBytes(CommandID);
   buffer[7]=temp[0];
   buffer[6]=temp[1];
   buffer[5]=temp[2];
   buffer[4]=temp[3];
   temp=BitConverter.GetBytes(SequenceID);
   buffer[11]=temp[0];
   buffer[10]=temp[1];
   buffer[9]=temp[2];
   buffer[8]=temp[3];
   return buffer;
  }
 }

 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_CONNECT
 {
  public CMPP_HEAD Head;
  
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
  public string SourceAddress;

  [ MarshalAs( UnmanagedType.ByValArray, SizeConst=16)]
  public Byte[] AuthenticatorSource;
  public Byte Version;
  public UInt32 TimeStamp;
  
  public Byte[] GetBuffer()
  {
   Byte[] temp=null;
   int iPos=0;
   Head.TotalLength=39;
   Byte[] buffer=new Byte[39];
   
   Byte[] HeadBuffer=this.Head.GetBuffer();
   Array.Copy(HeadBuffer,0,buffer,0,HeadBuffer.Length);
   iPos=iPos+HeadBuffer.Length;
   
   temp=Utility.Encode(SourceAddress,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+6;
   
   Array.Copy(AuthenticatorSource,0,buffer,iPos,AuthenticatorSource.Length);
   iPos=iPos+AuthenticatorSource.Length;
   
   buffer[iPos]=Version;
   iPos++;
   
   //temp=BitConverter.GetBytes(TimeStamp);
   temp=Utility.IntToNetBytes(TimeStamp);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   return buffer;
  }

 }
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_CONNECT_RESP
 {
  public CMPP_HEAD Head;
  public UInt32 Status;
  [ MarshalAs( UnmanagedType.ByValArray, SizeConst=16)]
  public Byte[] AuthenticatorISMG;
  public Byte Version;

 }
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_SUBMIT
 {
  public CMPP_HEAD Head;
  public UInt64 Msg_ID;
  public Byte Pk_Total;
  public Byte Pk_Number;
  public Byte Registered_Delivery;
  public Byte Msg_Level;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=10)]
  public string Service_Id;
  public Byte Fee_UserType;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=32)]
  public string Fee_Terminal_Id;
  public Byte Fee_Terminal_Type;
  public Byte TP_Pid;
  public Byte TP_Udhi;
  public Byte Msg_Fmt;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
  public string Msg_Src;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=2)]
  public string FeeType;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=6)]
  public string FeeCode;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=17)]
  public string Valid_Time; 
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=17)]
  public string At_Time; 
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=21)]
  public string Src_Id;
  public Byte DestUsr_Tl;
  public string[] Dest_Terminal_ID;
  public Byte Dest_Terminal_Type;
  public Byte Msg_Length;
  public string Msg_Content;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=20)]
  public String LinkID;

  public Byte[] GetBuffer()
  {
   
   int iPos=0;
   Msg_Length=(Byte)Utility.CountLength(Msg_Content.ToString(),(CODING)Msg_Fmt);
   Head.TotalLength=(UInt32)(163+32*DestUsr_Tl+Msg_Length);
   Byte[] buffer=new Byte[Head.TotalLength];
   Byte[] temp=null;
   
   Byte[] HeadBuffer=this.Head.GetBuffer();
   Array.Copy(HeadBuffer,0,buffer,0,HeadBuffer.Length);
   iPos=HeadBuffer.Length;
   
   temp=Utility.IntToNetBytes(Msg_ID);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   buffer[iPos]=Pk_Total;
   iPos++;

   buffer[iPos]=Pk_Number;
   iPos++;

   buffer[iPos]=Registered_Delivery;
   iPos++;

   buffer[iPos]=Msg_Level;
   iPos++;

   temp=Utility.Encode(Service_Id,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+10;

   buffer[iPos]=Fee_UserType;
   iPos++;

   temp=Utility.Encode(Fee_Terminal_Id,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+32;

   buffer[iPos]=Fee_Terminal_Type;
   iPos++;

   buffer[iPos]=TP_Pid;
   iPos++;
   
   buffer[iPos]=TP_Udhi;
   iPos++;

   buffer[iPos]=Msg_Fmt;
   iPos++;

   temp=Utility.Encode(Msg_Src,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+6;

   temp=Utility.Encode(FeeType,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+2;

   temp=Utility.Encode(FeeCode,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+6;

   temp=Utility.Encode(Valid_Time,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+17;

   temp=Utility.Encode(At_Time,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+17;
   
   temp=Utility.Encode(Src_Id,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+21;

   buffer[iPos]=DestUsr_Tl;
   iPos++;
   
   for(int i=0;i<DestUsr_Tl;i++)
   {
    temp=Utility.Encode(Dest_Terminal_ID[i],CODING.ASCII);
    Array.Copy(temp,0,buffer,iPos,temp.Length);
    iPos=iPos+32;
   }

   buffer[iPos]=Dest_Terminal_Type;
   iPos++;

   buffer[iPos]=Msg_Length;
   iPos++;

   temp=Utility.Encode(Msg_Content,(CODING)Msg_Fmt);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   temp=Utility.Encode(LinkID,CODING.ASCII);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   return buffer;

  }
 }


 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_SUBMIT_RESP
 {
  public CMPP_HEAD Head;
  public UInt64 Msg_ID;
  public UInt32 Result;

 }

 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_DELIVER
 {
  public CMPP_HEAD Head;
  public UInt64 Msg_ID;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=21)]
  public string Dest_Id;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=10)]
  public string Service_Id;
  public Byte TP_Pid;
  public Byte TP_Udhi;
  public Byte Msg_Fmt;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=10)]
  public string Src_Terminal_Id;
  public Byte Src_Terminal_Type;
  public Byte Registered_Delivery;
  public Byte Msg_Length;
  public string Msg_Content;
  [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=20)]
  public String LinkID;

  public bool Init(Byte[] buffer)
  {
   int iPos=0;
   bool bOK=true;
   try
   {
    Msg_ID=(UInt64)BitConverter.ToUInt64(buffer,0);
    iPos=iPos+8;

    Dest_Id=Utility.Decode(buffer,iPos,21,CODING.ASCII);
    iPos=iPos+21;

    Service_Id=Utility.Decode(buffer,iPos,10,CODING.ASCII);
    iPos=iPos+10;

    TP_Pid=buffer[iPos];
    iPos++;

    TP_Udhi=buffer[iPos];
    iPos++;

    Msg_Fmt=buffer[iPos];
    iPos++;

    Src_Terminal_Id=Utility.Decode(buffer,iPos,32,CODING.ASCII);
    iPos=iPos+32;

    Src_Terminal_Type=buffer[iPos];
    iPos++;

    Registered_Delivery=buffer[iPos];
    iPos++;

    Msg_Length=buffer[iPos];
    iPos++;

    if(Registered_Delivery==0)//是短消息
    {
     Msg_Content=Utility.Decode(buffer,iPos,Msg_Length,(CODING)Msg_Fmt);

    }
    else//是状态报告,先转为BASE64 String 存储
     Msg_Content=Convert.ToBase64String(buffer,iPos,Msg_Length);
    
    iPos=iPos+Msg_Length;
    LinkID=Utility.Decode(buffer,iPos,20,CODING.ASCII);
   }
   catch
   {
    bOK=false;
   }
   return bOK;

  }
  public CMPP_REPORT GetReport()
  {
   CMPP_REPORT Report=new CMPP_REPORT();
   if(Registered_Delivery==1)//是状态报告
   {
    Byte[] bytes=Convert.FromBase64String(Msg_Content);
    if((bytes!=null)&&(bytes.Length>0))
     Report.Init(bytes);
   }
   return Report;

  }

 }
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_REPORT
 {
  public UInt64 Msg_Id;
  public string Stat;
  public string Submit_Time;
  public string Done_Time;
  public string Dest_Terminal_Id;
  public UInt32 SMSC_Sequence;

  public bool Init(Byte[] buffer)
  {
   int iPos=0;
   bool bOK=true;
   try
   {
    Msg_Id=(UInt64)Utility.NetBytesToInt(buffer,0,8);
    iPos+=8;

    Stat=Utility.Decode(buffer,iPos,7,CODING.ASCII);
    iPos+=7;

    Submit_Time=Utility.Decode(buffer,iPos,10,CODING.ASCII);
    iPos+=10;

    Done_Time=Utility.Decode(buffer,iPos,10,CODING.ASCII);
    iPos+=10;

    Dest_Terminal_Id=Utility.Decode(buffer,iPos,32,CODING.ASCII);
    iPos+=32;

    SMSC_Sequence=(UInt32)Utility.NetBytesToInt(buffer,iPos,4);
   }
   catch
   {
    bOK=false;
   }
   return bOK;

 

  }
 }
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_DELIVER_RESP
 {
  public CMPP_HEAD Head;
  public UInt64 Msg_Id;
  public UInt32 Result;
  public Byte[] GetBuffer()
  {
   int iPos=0;
   Head.TotalLength=(UInt32)Marshal.SizeOf(this);
   Byte[] buffer=new Byte[Head.TotalLength];
   Byte[] temp=null;
   
   Byte[] HeadBuffer=this.Head.GetBuffer();
   Array.Copy(HeadBuffer,0,buffer,0,HeadBuffer.Length);
   iPos=HeadBuffer.Length;
   
   temp=BitConverter.GetBytes(Msg_Id);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   temp=Utility.IntToNetBytes(Result);
   Array.Copy(temp,0,buffer,iPos,temp.Length);
   iPos=iPos+temp.Length;

   return buffer;

  }
 }

 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_ACTIVE_TEST_RESP
 {
  public CMPP_HEAD Head;
  public Byte Reserved;
  public Byte[] GetBuffer()
  {
   int iPos=0;
   Head.TotalLength=(UInt32)Marshal.SizeOf(this);
   Byte[] buffer=new Byte[Head.TotalLength];
   
   Byte[] HeadBuffer=this.Head.GetBuffer();
   Array.Copy(HeadBuffer,0,buffer,0,HeadBuffer.Length);
   iPos=HeadBuffer.Length;

   buffer[iPos]=Reserved;

   return buffer;

  }
 }

 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_CANCEL
 {
  public CMPP_HEAD Head;
  public UInt64 MsgID;
  public Byte[] GetBuffer()
  {
   Byte[] buffer=new Byte[Marshal.SizeOf(this)];
   Byte[] HeadBuffer=this.Head.GetBuffer();
   int iPos=HeadBuffer.Length;
   Array.Copy(HeadBuffer,0,buffer,0,iPos);
   Byte[] temp=BitConverter.GetBytes(MsgID);
   buffer[iPos+7]=temp[0];
   buffer[iPos+6]=temp[1];
   buffer[iPos+5]=temp[2];
   buffer[iPos+4]=temp[3];
   buffer[iPos+3]=temp[4];
   buffer[iPos+2]=temp[5];
   buffer[iPos+1]=temp[6];
   buffer[iPos+0]=temp[7];

   return buffer;
  }
 }
 [ StructLayout( LayoutKind.Sequential, Pack=1,CharSet=CharSet.Ansi )]
 public struct CMPP_CANCEL_RESP
 {
  public CMPP_HEAD Head;
  public UInt32 SuccessID;
 }

 #endregion

}

【待续】

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:330667次
    • 积分:4613
    • 等级:
    • 排名:第6325名
    • 原创:81篇
    • 转载:153篇
    • 译文:1篇
    • 评论:43条
    最新评论