中国电信SMGP接口

下载参考程序 :http://download.csdn.net/detail/adama119/4189313 

短信行业已经很成熟了,到处可以找到资料。本人在这个行业干过几年,做过3套短信平台都在省级单位省用,做的最复杂的自然是SP的应用,曾经在广电集团工作时做的内容确实非常复杂自己都觉得头疼,当然也和水平有限有关。

2010年底给江苏某国企做了一套行业应用的短信系统,做短信平台大量工作还是围绕业务开发WEB方面内容。这次网关客户端的是用C#开发的,目标为50条/秒,性能上应该没什么问题,支持普通短信但是长短信对方没要就没写,需要的朋友可以自行修改开发。以下贴出SMGP3.0源代码给各位需要的朋友做个参考,运行到现在没有发现任何问题。这里只贴出SMGP接口,至于程序就自己做吧,如果需要也可以联系我

邮箱 spf193@gmail.com

 

//------------------------------------------------------------------------------

//文件Client.cs

//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Collections;


namespace AsiaINFO.SMS.SMGP3
{

    /// <summary>
    /// @Description:SMGP3 短消息电信网关客户端
    /// @Author:Adama SUN  
    /// @Mail:spf193@gmail.com

    /// @Copyright (C) 2010 AsiaINFO. All rights reserved.
    /// </summary>
    public class SMGPClient
    {
        public delegate void MsgEventDelegate(string msg);
        /// <summary>
        /// 线程状态通知
        /// </summary>
        /// <param name="sender">线程</param>
        /// <param name="state">线程状态</param>
        public delegate void ThreadStateDelegate(object sender, ThreadState state);

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="queue">SMGP接口 接收数据队列</param>
        /// <param name="syncEvents">SMGP接口信号:检查是否需要退出线程,SMGP接口新数据到达(通知)</param>
        public SMGPClient(Queue<byte[]> queue, SyncEvents syncEvents)
        {
            if (queue == null || syncEvents == null)
                throw new Exception("参数不能为空!");
            _receiveQueue = queue;
            _syncEvents = syncEvents;
        }

        #region private field

        private Queue<byte[]> _receiveQueue;//接收队列
        private SyncEvents _syncEvents;//信号

 

       // private string _Host;           //主机
       // private int _Port;              //端口
       // private string _ClientID;       //账号
       // private string _Password;       //密码
        private bool _IsConnected = false;      //连接状态
        private static object _SyncLockObject = new object();   //锁
        private TcpClient tc;
        private NetworkStream _NetworkStream;
        private Thread _ReadResponseThread;

        private object _syncIsConnectedObject = new object();

 


        #endregion


        #region public property

        /// <summary>
        /// 连接状态
        /// </summary>
        public bool IsConnected
        {
            get
            {
                lock (_syncIsConnectedObject)
                {
                    return this._IsConnected;
                }
            }
            set
            {
                lock (_syncIsConnectedObject)
                {
                    this._IsConnected = value;
                }
            }
        }


        #endregion

 

        #region public event

        /// <summary>
        /// 信息事件
        /// </summary>
        public event MsgEventDelegate MsgEvent;
        /// <summary>
        /// 错误事件
        /// </summary>
        public event MsgEventDelegate ErrorEvent;

        /// <summary>
        /// 退出事件
        /// </summary>
        public event ThreadStateDelegate ThreadStateEvent;

 

        #endregion

 


        #region public methos


        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="Host">主机地址</param>
        /// <param name="Port">端口</param>
        /// <param name="UserID">用户名</param>
        /// <param name="Password">密码</param>
        /// <param name="SequenceId">序列好</param>
        /// <returns></returns>
        public void Connect(string Host, int Port, string UserID, string Password, uint SequenceId)
        {
            Login login = new Login(UserID, Password, 2, DateTime.Now,0x30, SequenceId);

            tc = new TcpClient();
            tc.Connect(Host,Port);

            if (this._NetworkStream != null)
            {
                try
                {
                    this._NetworkStream.Close();
                    this._NetworkStream = null;
                }
                catch (Exception) { }
            }

            this._NetworkStream = tc.GetStream();
            this.WriteToStreamWithLock(login.ToBytes(), this._NetworkStream);
            this.StartRun();
        }


        /// <summary>
        /// 中断
        /// </summary>
        /// <param name="SequenceId"></param>
        public void Terminate(uint SequenceId)
        {
            MessageHeader terminate = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Exit, SequenceId);
            // OnMsg(terminate.ToString());
            this.WriteToStreamWithLock(terminate.ToBytes(), this._NetworkStream);
        }

        /// <summary>
        /// ACTIVE_TEST
        /// </summary>
        /// <param name="SequenceId"></param>
        public void ActiveTest(uint SequenceId)
        {
            MessageHeader activeTest = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test, SequenceId);
            this.WriteToStreamWithLock(activeTest.ToBytes(), this._NetworkStream);
        }

        /// <summary>
        /// ACTIVE_TEST_RESP
        /// </summary>
        /// <param name="SequenceId"></param>
        public void ActiveResp(uint SequenceId)
        {
            Active_Test_Resp response = new Active_Test_Resp(SequenceId);
            this.WriteToStreamWithLock(response.ToBytes(), this._NetworkStream);
        }

        /// <summary>
        /// 发送DELIVER_RESP
        /// </summary>
        /// <param name="Msg_Id"></param>
        /// <param name="Result"></param>
        public void DeliverResp(ulong Msg_Id, uint Result, uint SequenceId)
        {
            Deliver_Resp deliverResp = new Deliver_Resp(Msg_Id, Result, SequenceId);
            this.WriteToStreamWithLock(deliverResp.ToBytes(), this._NetworkStream);
        }

        /// <summary>
        /// 查询发送短信状态
        /// </summary>
        /// <param name="Time"></param>
        /// <param name="QueryType"></param>
        /// <param name="QueryCode"></param>
        /// <param name="Reserve"></param>
        /// <param name="SequenceId"></param>
        public void Query(DateTime Time, uint QueryType, string QueryCode, uint SequenceId)
        {
            Query query = new Query(Time, QueryType, QueryCode, SequenceId);
            this.WriteToStreamWithLock(query.ToBytes(), this._NetworkStream);
        }

 

 

        /// <summary>
        /// 发送短信
        /// </summary>
        /// <param name="ServiceID">业务代码</param>
        /// <param name="FeeType">资费类别</param>
        /// <param name="FeeCode">资费代码(以分为单位)</param>
        /// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
        /// <param name="SrcTermID">短消息发送方号码</param>>
        /// <param name="DestTermID">接收短信的号码_1个号码</param>
        /// <param name="MsgContent">短信内容</param>
        /// <param name="ProductID">产品ID</param>
        /// <param name="LinkID"></param>
        public void Submit(string ServiceID, string FeeType, string FeeCode, string FixedFee, string SrcTermID
            , string mobile, string MsgContent, string ProductID, string LinkID, uint SequenceId)
        {
            Submit(ServiceID, FeeType, FeeCode, FixedFee, SrcTermID, mobile, new string[] { mobile }, MsgContent, ProductID, LinkID, SequenceId);
        }


        /// <summary>
        /// 发送短信
        /// </summary>
        /// <param name="ServiceID">业务代码</param>
        /// <param name="FeeType">资费类别</param>
        /// <param name="FeeCode">资费代码(以分为单位)</param>
        /// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
        /// <param name="SrcTermID">短消息发送方号码</param>
        /// <param name="ChargeTermID">被计费用户的号码</param>
        /// <param name="DestTermID">接收短信的号码_多个号码</param>
        /// <param name="MsgContent">短信内容</param>
        /// <param name="ProductID">产品ID</param>
        /// <param name="LinkID"></param>
        public void Submit(string ServiceID, string FeeType, string FeeCode, string FixedFee, string SrcTermID, string ChargeTermID
            , string[] DestTermID, string MsgContent, string ProductID, string LinkID, uint SequenceId)
        {
            Submit(1, ServiceID, FeeType, FeeCode, FixedFee, SrcTermID, ChargeTermID, DestTermID, MsgContent, "", ProductID, LinkID, SequenceId);
        }


        /// <summary>
        /// 发送短信
        /// </summary>
        /// <param name="NeedReport">是否要返回状态确认报告</param>
        /// <param name="ServiceID">业务代码</param>
        /// <param name="FeeType">资费类别</param>
        /// <param name="FeeCode">资费代码(以分为单位)</param>
        /// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
        /// <param name="SrcTermID">短消息发送方号码</param>
        /// <param name="ChargeTermID">被计费用户的号码</param>
        /// <param name="DestTermID">接收短信的号码_多个号码</param>
        /// <param name="MsgContent">短信内容</param>
        /// <param name="Reserve">保留</param>
        /// <param name="ProductID">产品ID</param>
        /// <param name="LinkID"></param>
        public void Submit(uint NeedReport, string ServiceID, string FeeType, string FeeCode,string FixedFee,string SrcTermID,string ChargeTermID
            , string[] DestTermID, string MsgContent, string Reserve, string ProductID, string LinkID, uint SequenceId)
        {
            //这里的字段根据需要设定
            Submit submit = new Submit(SequenceId);

            submit.MsgType = 6;             //  uint    6=MT 消息(SP 发给终端,包括WEB 上发送的点对点短消息);
            submit.NeedReport = NeedReport; //  uint    0=不要求返回状态报告; 1=要求返回状态报告;
            submit.Priority = 1;
            submit.ServiceID = ServiceID;
            submit.FeeType=FeeType;
            submit.FeeCode=FeeCode;
            submit.FixedFee=FixedFee;
            submit.MsgFormat=15;
            submit.ValidTime = ""; //Util.Get_MMDDHHMMSS_String(DateTime.Now.AddHours(5)) + "032+";  // 存活有效期,格式遵循SMPP3.3协议。
            submit.AtTime="";   //Util.Get_MMDDHHMMSS_String(DateTime.Now) + "032+";     //      短消息定时发送时间,格式遵循SMPP3.3 以上版本协议。
            //submit.SrcTermID="118"+SrcTermID;
            submit.SrcTermID = SrcTermID;
            submit.ChargeTermID = ChargeTermID;
            submit.DestTermID=DestTermID;
            submit.DestTermIDCount=(uint)submit.DestTermID.Length;
            submit.MsgContent=MsgContent;
            submit.Reserve=Reserve;
            submit.ProductID=ProductID;
            submit.LinkID=LinkID;

            this.WriteToStreamWithLock(submit.ToBytes(), this._NetworkStream);
        }


        public void StartRun()
        {

            try
            {
                if (this._ReadResponseThread == null)
                {
                    this._ReadResponseThread = new Thread(new ThreadStart(this.Run));
                }

                if (this._ReadResponseThread.ThreadState == ThreadState.Unstarted)
                {
                    OnThreadState(ThreadState.Running);
                    this._ReadResponseThread.Start();
                }
                else if (this._ReadResponseThread.ThreadState == ThreadState.Suspended)
                {
                    OnThreadState(ThreadState.Running);
                    this._ReadResponseThread.Resume();
                }
                else if (this._ReadResponseThread.ThreadState == ThreadState.Stopped)
                {
                    OnThreadState(ThreadState.Running);
                    this._ReadResponseThread = null;
                    this._ReadResponseThread = new Thread(new ThreadStart(this.Run));
                    this._ReadResponseThread.Start();
                }

            }
            catch (Exception ex)
            {
                OnError("SMGPClient启动错误:" + ex.Message);
            }
        }

 

        /// <summary>
        /// 暂停线程
        /// </summary>
        public void Suspend()
        {
            try
            {
                if (this._ReadResponseThread != null && _ReadResponseThread.ThreadState != ThreadState.Stopped && _ReadResponseThread.ThreadState != ThreadState.Suspended)
                {
                    OnThreadState(ThreadState.Suspended);
                    this._ReadResponseThread.Suspend();

                }
            }
            catch (Exception) { }
        }


        /// <summary>
        /// 停止接收数据
        /// </summary>
        public void StopReceive()
        {
            _syncEvents.ExitThreadEvent.Set();
        }

        /// <summary>
        /// 退出
        /// </summary>
        public void Exit()
        {
            try
            {
                StopReceive();
                this._NetworkStream.Close();
                this._NetworkStream = null;
            }
            catch (Exception) { }
        }


        /// <summary>
        /// 是否已经停止
        /// </summary>
        /// <returns></returns>
        public bool IsStop()
        {
            if (_ReadResponseThread == null || _ReadResponseThread.ThreadState == ThreadState.Stopped || _ReadResponseThread.ThreadState == ThreadState.Aborted || _ReadResponseThread.ThreadState == ThreadState.AbortRequested)
                return true;
            return false;
        }

        /// <summary>
        /// 立刻停止
        /// </summary>
        /// <returns></returns>
        public void StopImmediately()
        {
            try
            {
                if (_ReadResponseThread != null)
                    _ReadResponseThread.Abort();
            }
            catch (ThreadAbortException) { }
            catch (Exception) { }
            finally
            {
                OnThreadState(ThreadState.Stopped);
            }

        }


        #endregion


        #region private method

        /// <summary>
        /// 信息通知
        /// </summary>
        private void OnMsg(string msg)
        {
            if (MsgEvent != null)
            {
                MsgEvent(msg);
            }
        }

        /// <summary>
        /// 错误通知
        /// </summary>
        /// <param name="type"></param>
        /// <param name="err"></param>
        private void OnError(string err)
        {
            if (ErrorEvent != null)
            {
                ErrorEvent(err);
            }
        }
        /// <summary>
        /// 退出
        /// </summary>
        protected void OnThreadState(ThreadState state)
        {
            if (ThreadStateEvent != null)
            {
                ThreadStateEvent(this, state);
            }
        }

 


        /// <summary>
        /// 写入流
        /// </summary>
        /// <param name="data"></param>
        /// <param name="Stream"></param>
        private void WriteToStreamWithLock(byte[] data, NetworkStream Stream)
        {
            try
            {
                lock (_SyncLockObject)
                {
                    Util.WriteToStream(data, Stream);
                }
            }
            catch (Exception ex)
            {
                IsConnected = false;
                OnError(ex.Message);
            }
        }

        /// <summary>
        /// 读取流
        /// </summary>
        /// <param name="Length"></param>
        /// <param name="Stream"></param>
        /// <returns></returns>
        private byte[] ReadFromStreamWithLock(int Length, NetworkStream Stream)
        {
            try
            {
                lock (_SyncLockObject)
                {
                    return Util.ReadFromStream(Length, Stream);
                }
            }
            catch (Exception ex)
            {
                IsConnected = false;
                OnError(ex.Message);
            }
            return null;
        }


        /// <summary>
        ///
        /// </summary>
        /// <param name="BreakFlag"></param>
        private void Run()
        {
            try
            {
                while (!_syncEvents.ExitThreadEvent.WaitOne(2, false))
                {
                    if (this._NetworkStream.CanRead)
                    {
                        if (this._NetworkStream.DataAvailable)
                        {
                            byte[] buffer = new byte[MessageHeader.Length]; //Header
                            buffer = this.ReadFromStreamWithLock(MessageHeader.Length, this._NetworkStream);

                            MessageHeader header = new MessageHeader(buffer);
                            byte[] bytes = new byte[header.PacketLength];
                            Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

                            int l = (int)header.PacketLength - MessageHeader.Length;
                            if (l > 0)
                            {
                                buffer = this.ReadFromStreamWithLock(l, this._NetworkStream);
                                Buffer.BlockCopy(buffer, 0, bytes, MessageHeader.Length, buffer.Length);
                            }
                            lock (((ICollection)_receiveQueue).SyncRoot)
                            {
                                _receiveQueue.Enqueue(bytes);
                            }
                            _syncEvents.NewItemEvent.Set();

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                IsConnected = false;
                OnError("SMGPClient接收错误:" + ex.Message);
            }
            OnThreadState(ThreadState.Stopped);

        }
        #endregion

    }
}

 

//------------------------------------------------------------------------------

//文件MessageEventArgs.cs

//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

 

namespace AsiaINFO.SMS.SMGP3
{
 
    /// <summary>
    /// 消息包
    /// </summary>
    public class MessageEventArgs : EventArgs
    {
        private byte[] _HeaderData;
        private MessageHeader _Header;
        private byte[] _BodyData;

        public byte[] BodyData
        {
            get
            {
                return this._BodyData;
            }
        }

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public byte[] HeaderData
        {
            get
            {
                return this._HeaderData;
            }
        }

        public MessageEventArgs(byte[] bytes)
        {
            this._HeaderData = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, this._HeaderData, 0, MessageHeader.Length);
            this._Header = new MessageHeader(this._HeaderData);
            this._BodyData = new byte[this._Header.PacketLength - MessageHeader.Length];
            Buffer.BlockCopy(bytes, MessageHeader.Length, this._BodyData, 0, this._BodyData.Length);
        }

    }
}

 

//------------------------------------------------------------------------------

//文件SMGPMessages.cs

//------------------------------------------------------------------------------

using System;
using System.Text;
using System.Security.Cryptography;
using System.Collections;


namespace AsiaINFO.SMS.SMGP3
{
    /// <summary>
    /// SMGP3 消息定义  (RequestId)
    /// </summary>
    public enum SMGP3_RequestId : uint
    {
        Login = 0x00000001          //客户端登录                ----sp use
            ,
        Login_Resp = 0x80000001     //客户端登录应答            ----sp use
            ,
        Submit = 0x00000002         //提交短消息                ----sp use
            ,
        Submit_Resp = 0x80000002    //提交短消息应答            ----sp use
            ,
        Deliver = 0x00000003        //下发短消息                ----sp use
            ,
        Deliver_Resp = 0x80000003   //下发短消息应答            ----sp use
            ,
        Active_Test = 0x00000004    //链路检测                  ----sp use
            ,
        Active_Test_Resp = 0x80000004   //链路检测应答          ----sp use
            ,
        Forward = 0x00000005            //短消息前转
            ,
        Forward_Resp = 0x80000005       //短消息前转应答
            ,
        Exit = 0x00000006               //退出请求              ----sp use
            ,
        ExitResp = 0x80000006               //退出应答          ----sp use
            ,
        Query = 0x00000007              //SP 统计查询
            ,
        Query_Resp = 0x80000007         //SP 统计查询应答
            ,
        Query_TE_Route = 0x00000008     //查询TE 路由
            ,
        Query_TE_Route_Resp = 0x80000008    //查询TE 路由应答
            ,
        Query_SP_Route = 0x00000009         //查询SP 路由
            ,
        Query_SP_Route_Resp = 0x80000009    //查询SP 路由应答
            ,
        Payment_Request = 0x0000000A          //扣款请求(用于预付费系统,参见增值业务计费方案)
            ,
        Payment_Request_Resp = 0x8000000A     //扣款请求响应(用于预付费系统,参见增值业务计费方案,下同)
            ,
        Payment_Affirm = 0x0000000B          //扣款确认(用于预付费系统,参见增值业务计费方案)
            ,
        Payment_Affirm_Resp = 0x8000000B     //扣款确认响应(用于预付费系统,参见增值业务计费方案)
            ,
        Query_UserState = 0x0000000C         //查询用户状态(用于预付费系统,参见增值业务计费方案)
            ,
        Query_UserState_Resp = 0x8000000C      //查询用户状态响应(用于预付费系统,参见增值业务计费方案)
            ,
        Get_All_TE_Route = 0x0000000D           //获取所有终端路由
            ,
        Get_All_TE_Route_Resp = 0x8000000D      //获取所有终端路由应答
            ,
        Get_All_SP_Route = 0x0000000E           //获取所有SP 路由
            ,
        Get_All_SP_Route_Resp = 0x8000000E      //获取所有SP 路由应答
            ,
        Update_TE_Route = 0x0000000F            //SMGW 向GNS 更新终端路由
            ,
        Update_TE_Route_Resp = 0x8000000F       //SMGW 向GNS 更新终端路由应答
            ,
        Update_SP_Route = 0x00000010            //SMGW 向GNS 更新SP 路由
            ,
        Update_SP_Route_Resp = 0x80000010       // SMGW 向GNS 更新SP 路由应答
            ,
        Push_Update_TE_Route = 0x00000011       //GNS 向SMGW 更新终端路由
            ,
        Push_Update_TE_Route_Resp = 0x80000011  //GNS 向SMGW 更新终端路由应答
            ,
        Push_Update_SP_Route = 0x00000012       //GNS 向SMGW 更新SP 路由
            ,
        Push_Update_SP_Route_Resp = 0x80000012  // GNS 向SMGW 更新SP 路由应答
    }

    /// <summary>
    /// 消息头
    /// </summary>
    public class MessageHeader
    {
        public const int Length = 4 + 4 + 4;

        public SMGP3_RequestId RequestId
        {
            get
            {
                return this._RequestId;
            }
        }

        public uint SequenceID
        {
            get
            {
                return this._SequenceID;
            }
        }

        public uint PacketLength
        {
            get
            {
                return this._PacketLength;
            }
        }

        private uint _PacketLength;             // 4 Unsigned Integer 数据包长度
        private SMGP3_RequestId _RequestId;     // 4 Unsigned Integer 命令或响应类型
        private uint _SequenceID;               // 4 Unsigned Integer 消息流水号

        public MessageHeader
         (
          uint PacketLength
          , SMGP3_RequestId RequestId
          , uint SequenceID
         ) //发送前
        {
            this._PacketLength = PacketLength;
            this._RequestId = RequestId;
            this._SequenceID = SequenceID;
        }

        public MessageHeader(byte[] bytes)
        {
            byte[] buffer = new byte[4];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._PacketLength = BitConverter.ToUInt32(buffer, 0);

            Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._RequestId = (SMGP3_RequestId)BitConverter.ToUInt32(buffer, 0);

            Buffer.BlockCopy(bytes, 8, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._SequenceID = BitConverter.ToUInt32(buffer, 0);
        }


        public byte[] ToBytes()
        {
            byte[] bytes = new byte[MessageHeader.Length];

            byte[] buffer = BitConverter.GetBytes(this._PacketLength);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 0, 4);

            buffer = BitConverter.GetBytes((uint)this._RequestId);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 4, 4);

            buffer = BitConverter.GetBytes(this._SequenceID);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 8, 4);

            return bytes;
        }
        public override string ToString()
        {
            return string.Format("MessageHeader: RequestId={0}    Sequence_Id={1}    Total_Length={2}"
              , this._RequestId
              , this._SequenceID
              , this._PacketLength
             );

        }

    }


    public class Login     
    {
        public const int BodyLength = 8 + 16 + 1 + 4+1;

        private string _ClientID;               // 8 Octet String 客户端用来登录服务器端的用户账号。
        private string _Password;
        private byte[] _AuthenticatorSource;    // 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:
        private uint _LoginMode;                // 1  Unsigned Integer  客户端用来登录服务器端的登录类型。
        //   AuthenticatorSource =
        //   MD5(Source_Addr+9 字节的0 +shared secret+timestamp)
        //   Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。
        private uint _ClientVersion;        // 1 Unsigned Integer 客户端支持的协议版本号
        private uint _Timestamp;       // 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。

        private MessageHeader _Header;

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public byte[] AuthenticatorSource
        {
            get
            {
                return this._AuthenticatorSource;
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="ClientID">客户端用来登录服务器端的用户账号</param>
        /// <param name="Password">登录密码</param>
        /// <param name="LoginMode">客户端用来登录服务器端的登录类型。0=发送短消息(send mode);1=接收短消息(receive mode);2=收发短消息(transmit mode);</param>
        /// <param name="Timestamp">时间戳</param>
        /// <param name="Version">客户端支持的协议版本号。</param>
        /// <param name="Sequence_Id"></param>
        public Login
         (
          string ClientID
          , string Password
          , uint LoginMode
          , DateTime Timestamp
          , uint ClientVersion
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length + BodyLength, SMGP3_RequestId.Login, Sequence_Id);

            this._ClientID = ClientID;
            this._Password = Password;
            this._LoginMode = LoginMode;

            string s = Util.Get_MMDDHHMMSS_String(Timestamp);
            this._Timestamp = UInt32.Parse(s);


            //byte[] buffer = new byte[8 + 7 + this._Password.Length + 10];
            //Encoding.ASCII.GetBytes(this._ClientID).CopyTo(buffer, 0);
            //Encoding.ASCII.GetBytes(this._Password).CopyTo(buffer, 8 + 7);
            //Encoding.ASCII.GetBytes(s).CopyTo(buffer, 8 + 7 + this._Password.Length);
            //this._AuthenticatorSource = new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);

            byte[] clientid = System.Text.Encoding.ASCII.GetBytes(ClientID);
            byte[] password = System.Text.Encoding.ASCII.GetBytes(Password);
            byte[] timestamp = System.Text.Encoding.ASCII.GetBytes(s);
            byte[] data = new byte[clientid.Length + 7 + password.Length + timestamp.Length];
            Array.Copy(clientid, data, clientid.Length);
            Array.Copy(password, 0, data, clientid.Length + 7, password.Length);
            Array.Copy(timestamp, 0, data, clientid.Length + 7 + password.Length, timestamp.Length);
            System.Security.Cryptography.MD5 MD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            _AuthenticatorSource = MD5.ComputeHash(data);

 

            this._ClientVersion = ClientVersion;
        }

        public byte[] ToBytes()
        {
            int i = 0;
            byte[] bytes = new byte[MessageHeader.Length + BodyLength];

            //header 12
            byte[] buffer = this._Header.ToBytes();
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //ClientID 8
            i += MessageHeader.Length;
            buffer = Encoding.ASCII.GetBytes(this._ClientID);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //AuthenticatorSource 16
            i += 8;
            buffer = this._AuthenticatorSource;
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //16

            //LoginMode 1
            i += 16;
            bytes[i++] = (byte)this._LoginMode; //登录类型

            //Timestamp
            buffer = BitConverter.GetBytes(this._Timestamp);
            Array.Reverse(buffer);
            buffer.CopyTo(bytes, i);

            //version 1
            i += 4;
            bytes[i] = (byte)this._ClientVersion; //客户端版本
            return (bytes);
        }

        public override string ToString()
        {
            return string.Format("Header={0}    AuthenticatorSource={1}    Password={2}    ClientID={3}   LoginMode={4}    Timestamp={5}    ClientVersion={6}"
                , this._Header.ToString()
                ,this._AuthenticatorSource
                , this._Password
                , this._ClientID
                , this._LoginMode
                ,this._Timestamp
                , this._ClientVersion);
        }
    }


    public class Login_Resp
    {
        private MessageHeader _Header;
        public const int BodyLength = 4 + 16 + 1;

        private uint _Status;    // 4 Unsigned Integer 状态
        //   0:正确
        //   1:消息结构错
        //   2:非法源地址
        //   3:认证错
        //   4:版本太高
        //   5~:其他错误
        private byte[] _AuthenticatorISMG; // 16 Octet String ISMG认证码,用于鉴别ISMG。
        //   其值通过单向MD5 hash计算得出,表示如下:
        //   AuthenticatorISMG =MD5(Status+AuthenticatorSource+shared secret),Shared secret 由中国移动与源地址实体事先商定,AuthenticatorSource为源地址实体发送给ISMG的对应消息CMPP_Connect中的值。
        //    认证出错时,此项为空。
        private uint _ServerVersion;    // 1 Unsigned Integer 服务器端支持的最高版本号

        public byte[] AuthenticatorISMG
        {
            get
            {
                return this._AuthenticatorISMG;
            }
        }
        /// <summary>
        /// 请求返回结果
        /// </summary>
        public uint Status
        {
            get
            {
                return this._Status;
            }
        }
        /// <summary>
        /// 服务器版本号
        /// </summary>
        public uint ServerVersion
        {
            get
            {
                return this._ServerVersion;
            }
        }

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public Login_Resp(byte[] bytes)
        {
            //header 12
            int i = 0;
            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            this._Header = new MessageHeader(buffer);

            //status 4
            i += MessageHeader.Length;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._Status = BitConverter.ToUInt32(buffer, 0);

            //AuthenticatorISMG 16
            i += 4;
            this._AuthenticatorISMG = new byte[16];
            Buffer.BlockCopy(bytes, MessageHeader.Length + 4, this._AuthenticatorISMG, 0, this._AuthenticatorISMG.Length);

            //version  1
            i += 16;
            this._ServerVersion = bytes[i];
        }

        public override string ToString()
        {

            return string.Format("Header={0}    AuthenticatorISMG={1}    BodyLength={2}    Status={3}    ServerVersion={4}"
                , this._Header.ToString()
                , this._AuthenticatorISMG
                , Login_Resp.BodyLength
                , this._Status
                , this._ServerVersion);
        }

    }


    public class Submit
    {
        private int _BodyLength;

        public const int FixedBodyLength = 1
                 + 1
                 + 1
                 + 10
                 + 2
                 + 6
                 + 6
                 + 1
                 + 17
                 + 17
                 + 21
                 + 21
                 + 1
            //+ 21*DestTermIDCount (_DestTermID字段)
                 + 1
            //+ MsgLength (Msg_Content字段)
                 + 8;
            // tlv

        private uint _MsgType;          // 1 Unsigned Integer 短消息类型。
        private uint _NeedReport;       // 1 Unsigned Integer 是否要求返回状态报。
        private uint _Priority;         // 1 Unsigned Integer 短消息发送优先级。
        private string _ServiceID;      // 10 Octet String 业务代码
        private string _FeeType;          // 2 Octet String 收费类型。
        private string _FeeCode;        // 6 Octet String 资费代码。
        private string _FixedFee;         // 6 Octet String 包月费/封顶费
        private uint _MsgFormat;        // 1 Unsigned Integer 短消息格式
        private string _ValidTime;      // 17 Octet String 短消息有效时间。
        private string _AtTime;         // 17 Octet String 短消息定时发送时间,格式遵循SMPP3.3协议。
        private string _SrcTermID;      // 21 Octet String 短信息发送方号码
        private string _ChargeTermID;   // 21 Octet String 计费用户号码
        private uint _DestTermIDCount;  // 1 Unsigned Integer 短消息接收号码总数。
        private string[] _DestTermID;   // 21*DestTermIDCount Octet String 短消息接收号码。
        private uint _MsgLength;        // 1 Unsigned Integer 短消息长度
        private string _MsgContent;     // MsgLength Octet String 短消息内容。
        private string _Reserve;        // 8 Octet String 保留

        // tlv
        private string _ProductID = "";
        private string _LinkID = "";
        private Tlv[] _OtherTlvArray = null;


        public MessageHeader Header
        {
            get
            {
                return _Header;
            }
            set
            {
                _Header = value;
            }
        }
        private MessageHeader _Header;

        private uint _Sequence_Id;

        public Submit(uint Sequence_Id)
        {
            this._Sequence_Id = Sequence_Id;
        }


        private byte[] _MsgContent_Bytes;
        private void SetHeader()
        {
            //byte[] buf;
            switch (this._MsgFormat)
            {
                case 8:
                    _MsgContent_Bytes = Encoding.BigEndianUnicode.GetBytes(this._MsgContent);
                    break;
                case 15: //gb2312
                    _MsgContent_Bytes = Encoding.GetEncoding("gb2312").GetBytes(this._MsgContent);
                    break;
                case 0: //ascii
                case 3: //短信写卡操作
                case 4: //二进制信息
                default:
                    _MsgContent_Bytes = Encoding.ASCII.GetBytes(this._MsgContent);
                    break;
            }

            this._MsgLength = (uint)_MsgContent_Bytes.Length;
            this._BodyLength = (int)(FixedBodyLength + 21 * this._DestTermID.Length + this._MsgLength);
            if (_OtherTlvArray != null)
            {
                for (int i = 0; i < _OtherTlvArray.Length; i++)
                {
                    if(_OtherTlvArray[i].Length>0)
                        _BodyLength += _OtherTlvArray[i].Length + 4;
                }
            }
            this._Header = new MessageHeader((uint)(MessageHeader.Length + this._BodyLength), SMGP3_RequestId.Submit, this._Sequence_Id);
        }

        public byte[] ToBytes()
        {
            //Msg_Length Msg_Content

            int i = 0;
            byte[] bytes = new byte[MessageHeader.Length + this._BodyLength];
            byte[] buffer = this._Header.ToBytes();
            Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);
            i += MessageHeader.Length;


            bytes[i++] = (byte)this._MsgType;       //[12,12]
            bytes[i++] = (byte)this._NeedReport;    //[13,13]
            bytes[i++] = (byte)this._Priority;      //[14,14]

            //ServiceId 
            buffer = Encoding.ASCII.GetBytes(this._ServiceID);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10 //[15,24]

            //FeeType
            i += 10;
            buffer = Encoding.ASCII.GetBytes(this._FeeType);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //2 //[25,26]

            //FeeCode
            i += 2;
            buffer = Encoding.ASCII.GetBytes(this._FeeCode);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[27,32]

            //FixedFee
            i += 6;
            buffer = Encoding.ASCII.GetBytes(this._FixedFee);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[33,38]

            //MsgFormat
            i += 6;
            bytes[i++] = (byte)this._MsgFormat;      //1 //[39,39]

            //ValId_Time
            buffer = Encoding.ASCII.GetBytes(this._ValidTime);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[40,56]

            //AtTime
            i += 17;
            buffer = Encoding.ASCII.GetBytes(this._AtTime);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[57,73]

            //SrcTermID
            i += 17;
            buffer = Encoding.ASCII.GetBytes(this._SrcTermID);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21 //[74,94]

            //ChargeTermID
            i += 21;
            buffer = Encoding.ASCII.GetBytes(this._ChargeTermID);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21 //[95,115]

            //DestTermIDCount
            i += 21;
            this._DestTermIDCount = (uint)this._DestTermID.Length;
            bytes[i++] = (byte)this._DestTermIDCount;            //1 //[116,116]

            //DestTermID
            foreach (string s in this._DestTermID)
            {
                buffer = Encoding.ASCII.GetBytes(s);
                Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
                i += 21;
            }

            //MsgLength
            bytes[i++] = (byte)this._MsgLength;

            //MsgContent
            //buffer = Encoding.
            Buffer.BlockCopy(this._MsgContent_Bytes, 0, bytes, i, this._MsgContent_Bytes.Length);


            //Reserve
            i += (int)this._MsgLength;
            buffer = Encoding.ASCII.GetBytes(this._Reserve);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //8


            //tlv
            i += 8;

            if (_OtherTlvArray != null)
            {
                for (int j = 0; j < _OtherTlvArray.Length; j++)
                {
                    if (_OtherTlvArray[j].Length > 0)
                    {
                        Buffer.BlockCopy(_OtherTlvArray[j].TlvBuf, 0, bytes, i, _OtherTlvArray[j].Length); //8
                        i += _OtherTlvArray[j].Length;
                    }
                }
            }

            return bytes;

        }

        public void AddTlv(short tag, string value)
        {

            if (this._OtherTlvArray == null)
            {
                Tlv[] tmp = new Tlv[1];
                tmp[0] = new Tlv(tag, value);
                this._OtherTlvArray = tmp;
            }
            else
            {
                int find = 0;
                for (int i = 0; i < _OtherTlvArray.Length; i++)
                {
                    if (_OtherTlvArray[i].Tag == tag)
                    {
                        find = 1;
                        _OtherTlvArray[i] = new Tlv(tag, value);
                    }
                }
                if (find == 0)
                {
                    Tlv[] tmp = new Tlv[_OtherTlvArray.Length + 1];
                    Array.Copy(_OtherTlvArray, tmp, _OtherTlvArray.Length);
                    //Buffer.BlockCopy(_OtherTlvArray, 0, tmp, 0, _OtherTlvArray.Length);
                    tmp[_OtherTlvArray.Length] = new Tlv(tag, value);
                    this._OtherTlvArray = tmp;
                }
            }

            this.SetHeader();

            //if (tag == TlvId.LinkID)
            //{
            //    this._LinkID = value;
            //}
            //else if (tag == TlvId.Mserviceid)
            //{
            //    this._ProductID = value;
            //}
            //else
            //{
            //    if (this.OtherTlvArray == null)
            //    {
            //        Tlv[] tmp = new Tlv[1];
            //        tmp[0] = new Tlv(tag, value);
            //        this.OtherTlvArray = tmp;
            //    }
            //    else
            //    {
            //        int find = 0;
            //        for (int i = 0; i < OtherTlvArray.Length; i++)
            //        {
            //            if (OtherTlvArray[i].Tag == tag)
            //            {
            //                find = 1;
            //                OtherTlvArray[i] = new Tlv(tag, value);
            //            }
            //        }
            //        if (find == 0)
            //        {
            //            Tlv[] tmp = new Tlv[OtherTlvArray.Length + 1];
            //            Buffer.BlockCopy(OtherTlvArray, 0, tmp, 0, OtherTlvArray.Length);
            //            tmp[OtherTlvArray.Length] = new Tlv(tag, value);
            //            this.OtherTlvArray = tmp;
            //        }
            //    }
            //}
        }

 

        /// <summary>
        /// 短消息类型
        ///
        /// 对于回执消息该字段无效;对于文本短消息,该字段表示短消息的消息流向:
        /// 0=MO 消息(终端发给SP);
        /// 6=MT 消息(SP 发给终端,包括WEB 上发送的点对点短消息);
        /// 7=点对点短消息;
        /// </summary>
        public uint MsgType
        {
            get
            {
                return this._MsgType;
            }
            set
            {
                this._MsgType = value;
            }
        }

        /// <summary>
        /// 是否要求返回状态报告
        /// 0=不要求返回状态报告;
        /// 1=要求返回状态报告;
        /// </summary>
        public uint NeedReport
        {
            get
            {
                return this._NeedReport;
            }
            set
            {
                this._NeedReport = value;
            }
        }

        /// <summary>
        /// 短消息发送优先级。
        /// 0=低优先级;
        /// 1=普通优先级;
        /// 2=较高优先级;
        /// 3=高优先级;
        /// </summary>
        public uint Priority
        {
            get
            {
                return this._Priority;
            }
            set
            {
                this._Priority = value;
            }
        }

        /// <summary>
        /// 业务代码
        /// </summary>
        public string ServiceID
        {
            get
            {
                return this._ServiceID;
            }
            set
            {
                this._ServiceID = value;
            }
        }

        /// <summary>
        /// 对计费用户采取的收费类型。
        ///
        /// 00=免费,此时FixedFee 和FeeCode 无效;
        /// 01=按条计信息费,此时FeeCode 表示每条费用,FixedFee 无效;
        /// 02=按包月收取信息费,此时FeeCode 无效,FixedFee 表示包月费用;
        /// 03=按封顶收取信息费,若按条收费的费用总和达到或超过封顶费后,则按照封顶费用收取信息费;
        ///     若按条收费的费用总和没有达到封顶费用,则按照每条费用总和收取信息费。FeeCode表示每条费用,FixedFee 表示封顶费用。
        /// </summary>
        public string FeeType
        {
            get
            {
                return this._FeeType;
            }
            set
            {
                this._FeeType = value;
            }
        }


        /// <summary>
        /// 每条短消息费率
        ///
        /// 单位为“分”。
        /// </summary>
        public string FeeCode
        {
            get
            {
                return this._FeeCode;
            }
            set
            {
                this._FeeCode = value;
            }
        }

 

        /// <summary>
        /// 短消息的包月费/封顶费
        ///
        /// 单位为“分”
        /// </summary>
        public string FixedFee
        {
            get
            {
                return this._FixedFee;
            }
            set
            {
                this._FixedFee = value;
            }
        }

 

        /// <summary>
        /// 短消息内容体的编码格式。
        ///
        /// 0=ASCII 编码;
        /// 3=短消息写卡操作;
        /// 4=二进制短消息;
        /// 8=UCS2 编码;
        /// 15=GB18030 编码;
        /// 246(F6)=(U)SIM 相关消息;
        /// 对于文字短消息,要求MsgFormat=15。对于回执消息,要求MsgFormat=0。
        /// </summary>
        public uint MsgFormat
        {
            get
            {
                return this._MsgFormat;
            }
            set
            {
                this._MsgFormat = value;
                if (this._MsgContent != null)
                {
                    this.SetHeader();
                }
            }
        }

 

        /// <summary>
        /// 短消息有效时间
        ///
        /// 格式遵循SMPP3.3 以上版本协议
        /// 短消息有效时间在转发过程中保持不变
        /// </summary>
        public string ValidTime
        {
            get
            {
                return this._ValidTime;
            }
            set
            {
                this._ValidTime = value;
            }
        }

 

        /// <summary>
        /// 短消息定时发送时间
        ///
        /// 格式遵循SMPP3.3 以上版本协议
        /// 短消息定时发送时间在转发过程中保持不变
        /// </summary>
        public string AtTime
        {
            get
            {
                return this._AtTime;
            }
            set
            {
                this._AtTime = value;
            }
        }

 

        /// <summary>
        /// 短消息发送方号码。
        ///
        /// 对于MT 消息,SrcTermID 格式为“118+SP 服务代码+其它(可选)”
        /// 例如SP 服务代码为1234 时,SrcTermID 可以为1181234 或118123456 等。
        /// </summary>
        public string SrcTermID
        {
            get
            {
                return this._SrcTermID;
            }
            set
            {
                this._SrcTermID = value;
            }
        }


        /// <summary>
        /// 计费用户号码
        ///
        /// ChargeTermID 为空时,表示对被叫用户号码计费;
        /// ChargeTermID 为非空时,表示对计费用户号码计费。
        /// </summary>
        public string ChargeTermID
        {
            get
            {
                return this._ChargeTermID;
            }
            set
            {
                this._ChargeTermID = value;
            }
        }

 

        /// <summary>
        /// 短消息接收号码总数(≤100),用于SP 实现群发短消息。
        /// </summary>
        public uint DestTermIDCount
        {
            get
            {
                return this._DestTermIDCount;
            }
            set
            {
                this._DestTermIDCount = value;
            }
        }

        /// <summary>
        /// 短消息接收号码。
        /// </summary>
        public string[] DestTermID
        {
            get
            {
                return this._DestTermID;
            }
            set
            {
                this._DestTermID = value;
            }
        }

 

        /// <summary>
        /// 短消息长度
        ///
        /// 指MsgContent 域的长度,取值大于或等于0。对于MT 消息,取值应小于或等于140
        /// </summary>
        public uint MsgLength
        {
            get
            {
                return this._MsgLength;
            }
            set
            {
                _MsgLength = value;
            }
        }


        /// <summary>
        /// 短消息内容
        /// </summary>
        public string MsgContent
        {
            get
            {
                return this._MsgContent;
            }
            set
            {
                this._MsgContent = value;
                this.SetHeader();
            }
        }

        /// <summary>
        /// 保留字段
        /// </summary>
        public string Reserve
        {
            get
            {
                return this._Reserve;
            }
            set
            {
                this._Reserve = value;
            }
        }

        /// <summary>
        /// 产品ID   =MServiceID
        /// </summary>
        public string ProductID
        {
            get { return _ProductID; }
            set {
                _ProductID = value;
                AddTlv(TlvId.Mserviceid, _ProductID);
                this.SetHeader();
            }
        }


        public string LinkID
        {
            get { return _LinkID; }
            set {
                _LinkID = value;
                AddTlv(TlvId.LinkID, _LinkID);
                this.SetHeader();
            }
        }


        public Tlv[] OtherTlvArray
        {
            get { return _OtherTlvArray; }
            //set { _OtherTlvArray = value; }
        }

 


        public override string ToString()
        {
            return "[/r/n"
               + this._Header.ToString() + "/r/n"
               + string.Format
               (
                "/tMessageBody:"
                + "/r/n/t/tMsgType: {0}"
                + "/r/n/t/tNeedReport: {1}"
                + "/r/n/t/tPriority: {2}"
                + "/r/n/t/tServiceID: {3}"
                + "/r/n/t/tFeeType: {4}"
                + "/r/n/t/tFeeCode: {5}"
                + "/r/n/t/tFixedFee: {6}"
                + "/r/n/t/tMsgFormat: {7}"
                + "/r/n/t/tValidTime: {8}"
                + "/r/n/t/tAtTime: {9}"
                + "/r/n/t/tSrcTermID: {10}"
                + "/r/n/t/tChargeTermID: {11}"
                + "/r/n/t/tDestTermIDCount: {12}"
                + "/r/n/t/tDestTermID: {13}"
                + "/r/n/t/tMsgLength: {14}"
                + "/r/n/t/tMsgContent: {15}"
                + "/r/n/t/tReserve: {16}"
                + "/r/n/t/tProductID: {17}"
                + "/r/n/t/tLinkID: {18}"
                + "/r/n/t/tOtherTlvArray: {19}"
                , this._MsgType
                , this._NeedReport
                , this._Priority
                , this._ServiceID
                , this._FeeType
                , this._FeeCode
                , this._FixedFee
                , this._MsgFormat
                , this._ValidTime
                , this._AtTime
                , this._SrcTermID
                , this._ChargeTermID
                , this._DestTermIDCount
                , String.Join(",", this._DestTermID)
                , this._MsgLength
                , this._MsgContent
                , this._Reserve
                , this._ProductID
                , this._LinkID
                , this._OtherTlvArray.ToString()
               )
             + "/r/n]";
        }

    }

 

    public class Submit_Resp
    {
        private MessageHeader _Header;
        private string _MsgID;
        private uint _Result;

        public const int BodyLength = 10 + 4;

        /// <summary>
        /// 短消息流水号
        /// </summary>
        public string MsgID
        {
            get
            {
                return this._MsgID;
            }
        }

        /// <summary>
        /// 请求返回结果
        /// </summary>
        public uint Result
        {
            get
            {
                return this._Result;
            }
        }


        public MessageHeader Header
        {
            get
            {

                return this._Header;
            }
        }

        public Submit_Resp(byte[] bytes)
        {
            int i = 0;
            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            this._Header = new MessageHeader(buffer);

            //string s = null;
            MsgId 10
            //i += MessageHeader.Length;
            //buffer = new byte[10];
            //Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            //s = Encoding.ASCII.GetString(buffer).Trim();
            //s = s.Substring(0, s.IndexOf('/0'));
            //this._MsgID = s;

            //Msg_Id
            i += MessageHeader.Length;
            buffer = new byte[10];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            this._MsgID = System.BitConverter.ToString(buffer);
       //     string test = System.BitConverter.ToString(buffer);
       //     System.Console.WriteLine("Submit_Resp=" + test);

           // Array.Reverse(buffer);
           // this._MsgID = BitConverter.ToUInt32(buffer, 0);
;

            //Result
            i += 10;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._Result = BitConverter.ToUInt32(buffer, 0);
        }


        public override string ToString()
        {
            return string.Format("Header={0}    Msg_Id={1}    tResult={2}"
                , this._Header.ToString()
                , this._MsgID
                , this._Result);
        }
    }


    public class Deliver
    {
        private ulong _MsgID;
        /// <summary>
        /// 短消息流水号
        /// </summary>
        public ulong MsgID
        {
            get{ return _MsgID;}
        }

        private uint _IsReport;
        /// <summary>
        /// 是否为状态报告
        ///
        /// 0=不是状态报告;
        /// 1=是状态报告;
        /// </summary>
        public uint IsReport
        {
            get{    return _IsReport;}
        }

        private uint _MsgFormat;
        /// <summary>
        /// 短消息格式
        ///
        /// 0=ASCII 编码;
        /// 3=短消息写卡操作
        /// 4=二进制短消息;
        /// 8=UCS2 编码;
        /// 15=GB18030 编码;
        /// 246(F6)=(U)SIM 相关消息;
        /// </summary>
        public uint MsgFormat
        {
            get{ return _MsgFormat;}
        }


        private string _RecvTime;
        /// <summary>
        /// 短消息接收时间
        ///
        /// 格式为YYYYMMDDHHMMSS(年年年年月月日日时时分分秒秒
        /// </summary>
        public string RecvTime
        {
            get{ return _RecvTime;}
        }


        private string _SrcTermID;
        /// <summary>
        /// 短消息发送号码
        /// </summary>
        public string SrcTermID
        {
            get{return _SrcTermID;}
        }

        private string _DestTermID;
        /// <summary>
        /// 短消息接收号码
        ///
        /// 格式为“118+SP 服务代码+其它(可选)
        /// </summary>
        public string DestTermID
        {
            get{return _DestTermID;}
        }


        private uint _MsgLength;
        /// <summary>
        /// 短消息长度
        /// </summary>
        public uint MsgLength
        {
            get{return _MsgLength;}
        }


        private string _MsgContent;
        /// <summary>
        /// 短消息内容
        /// </summary>
        public string MsgContent
        {
            get{return _MsgContent;}
        }

        private byte[] _Report;
        /// <summary>
        /// 状态报告
        /// </summary>
        public byte[] Report
        {
            get { return _Report; }

        }

 

        private string _Reserve;
        /// <summary>
        /// 保留
        /// </summary>
        public string Reserve
        {
            get{return _Reserve;}
        }


        private string _LinkID;
        public string LinkID
        {
            get { return _LinkID; }
        }

        private uint _TP_udhi;
        public uint TP_udhi
        {
            get { return _TP_udhi; }
        }

        //private string _ReportMsgID;
        //public string ReportMsgID
        //{
        //    get { return _ReportMsgID; }
        //}
        private Tlv[] _OtherTlv;
        public Tlv[] OtherTlv
        {
            get { return _OtherTlv; }
        }


        private MessageHeader _Header;

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public const int FixedBodyLength = 10 // MsgId Octet String 信息标识。
                 + 1    // IsReport Unsigned Integer 是否为状态报告。
                 + 1    // MsgFormat Unsigned Integer 短消息格式。
                 + 14   // RecvTime Octet String 短消息接收时间
                 + 21   // SrcTermID Unsigned String 短消息发送号码。
                 + 21   // DestTermID Unsigned String 短消息接收号码
                 + 1    // MsgLength Unsigned Integer 短消息长度。
           //MsgLength  // MsgContent Octet String 短消息内容。
                 + 8;   // Reserve Octet String 保留。
            // tlv
        private int _BodyLength;
        public int BodyLength
        {
            get
            {
                return this._BodyLength;
            }
        }

 

        public Deliver(byte[] bytes)
        {
            int i = 0;

            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, MessageHeader.Length);
            this._Header = new MessageHeader(buffer);

            string s = null;
            //MsgId 10
            //i += MessageHeader.Length;
            //buffer = new byte[10];
            //Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            //s = Encoding.ASCII.GetString(buffer).Trim();
            //s = s.Substring(0, s.IndexOf('/0'));
            //this._MsgID = s;

            i += MessageHeader.Length;
            buffer = new byte[10];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MsgID = BitConverter.ToUInt32(buffer, 0);

 

            //IsReport 1
            i += 10;
            this._IsReport = (uint)bytes[i++];
            this._MsgFormat = (uint)bytes[i++];


            //RecvTime 14
            buffer = new byte[14];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if(s.IndexOf('/0')>0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._RecvTime = s;


            //SrcTermID 21
            i += 14;
            buffer = new byte[21];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._SrcTermID = s;


            //DestTermID 21
            i += 21;
            buffer = new byte[21];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._DestTermID = s;


            //MsgLength 1
            i += 21;
            this._MsgLength = (uint)bytes[i++];


            //MsgContent
            buffer = new byte[this._MsgLength];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            if (this._IsReport == 1)
            {   ///状态报告 保存至Report
                this._MsgContent = "";
                this._Report = new byte[_MsgLength];
                Buffer.BlockCopy(buffer, 0, _Report, 0, _Report.Length);
            }
            else
            {
                ///短信 保存至Msg_Content
                switch (this._MsgFormat)
                {
                    case 8:
                        this._MsgContent = Encoding.BigEndianUnicode.GetString(buffer).Trim();
                        break;
                    case 15: //gb2312
                        this._MsgContent = Encoding.GetEncoding("gb2312").GetString(buffer).Trim();
                        break;
                    case 0: //ascii
                    case 3: //短信写卡操作
                    case 4: //二进制信息
                    default:
                        this._MsgContent = Encoding.ASCII.GetString(buffer).ToString();
                        break;
                }
            }
            //Reserve 8
            i += (int)this._MsgLength;
            buffer = new byte[8];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._Reserve = s;
           
            //tlv  --剩余全部
            i += 8;
          //  buffer = new byte[bytes.Length - i];
          //  Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            ArrayList tmptlv = new ArrayList();
            for (; i < bytes.Length; )
            {
                //Tag 2
                buffer = new byte[2];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                Array.Reverse(buffer);
                short tlv_Tag = BitConverter.ToInt16(buffer, 0);

                //Length 2
                i += 2;
                buffer = new byte[2];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                Array.Reverse(buffer);
                short tlv_Length = BitConverter.ToInt16(buffer, 0);
                i += 2;

                String tlv_Value = "";
                if (tlv_Tag == TlvId.Mserviceid || tlv_Tag == TlvId.SrcTermPseudo
                        || tlv_Tag == TlvId.DestTermPseudo
                        || tlv_Tag == TlvId.ChargeTermPseudo
                        || tlv_Tag == TlvId.LinkID)
                {

                    buffer = new byte[tlv_Length];
                    Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                    s = Encoding.ASCII.GetString(buffer).Trim();
                    if (s.IndexOf('/0') > 0)
                        s = s.Substring(0, s.IndexOf('/0'));
                    tlv_Value = s;
                    i += tlv_Length;
                }
                else
                {
                     tlv_Value=((uint)bytes[i++]).ToString();
                }


                if (tlv_Tag == (short)TlvId.TP_udhi)
                {
                    this._TP_udhi = uint.Parse(tlv_Value);
                }
                else if (tlv_Tag == (short)TlvId.LinkID)
                {
                    this._LinkID = tlv_Value;
                }
                else
                {
                    tmptlv.Add(new Tlv(tlv_Tag, tlv_Value));
                }


                if (tmptlv.Count > 0)
                {
                    this._OtherTlv = new Tlv[tmptlv.Count];
                    int j = 0;
                    foreach (Object tmp in tmptlv)
                    {
                        this.OtherTlv[j++] = (Tlv)tmp;
                    }

                }
            }

        }


        public override string ToString()
        {
            return "[/r/n"
             + this._Header.ToString() + "/r/n"
             + string.Format
              (
               "/tMessageBody:"
               + "/r/n/t/tMsgID: {0}"
               + "/r/n/t/tIsReport: {1}"
               + "/r/n/t/tMsgFormat: {2}"
               + "/r/n/t/tRecvTime: {3}"
               + "/r/n/t/tSrcTermID: {4}"
               + "/r/n/t/tDestTermID: {5}"
               + "/r/n/t/tMsgLength: {6}"
               + "/r/n/t/tMsgContent: {7}"
               + "/r/n/t/tReserve: {8}"
               + "/r/n/t/tLinkID: {9}"
               + "/r/n/t/tTP_udhi: {10}"
               + "/r/n/t/tOtherTlv: {11}"
               , this._MsgID
               , this._IsReport
               , this._MsgFormat
               , this._RecvTime
               , this._SrcTermID
               , this._DestTermID
               , this._MsgLength
               , this._MsgContent
               , this._Reserve
               , this._LinkID
               , this._TP_udhi
               , this._OtherTlv.ToString()
              )
             + "/r/n]";
        }
    }


    public class Deliver_Resp
    {
        private MessageHeader _Header;
        private ulong _MsgID;
        private uint _Result;
        public const int Bodylength = 10 + 4;

        private uint _Sequence_Id;

        public Deliver_Resp(ulong MsgID, uint Result,uint Sequence_Id)
        {
            this._MsgID = MsgID;
            this._Result = Result;
            this._Sequence_Id = Sequence_Id;
        }

        public byte[] ToBytes()
        {
            int i = 0;
            byte[] bytes = new byte[MessageHeader.Length + Bodylength];

            byte[] buffer = new byte[MessageHeader.Length];
            //header
            this._Header = new MessageHeader(MessageHeader.Length + Bodylength, SMGP3_RequestId.Deliver_Resp, _Sequence_Id);
            buffer = this._Header.ToBytes();
            Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

            //MsgID 10
            i += MessageHeader.Length;
            //buffer = Encoding.ASCII.GetBytes(this._MsgID);
           // Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
            buffer = BitConverter.GetBytes(this._MsgID);
            Array.Reverse(buffer);
            buffer.CopyTo(bytes, i);

            //Status 4
            i += 10;
            buffer = BitConverter.GetBytes(this._Result);
            Array.Reverse(buffer);
            buffer.CopyTo(bytes, i);
            return bytes;

        }

        public override string ToString()
        {
            return this._Header.ToString() + "/r/n"
             + string.Format
              (
               "[/r/nMessageBody:"
               + "/r/n/tMsgID: {0}"
               + "/r/n/tResult: {1}"
               + "/r/n]"
               , this._MsgID
               , this._Result
              );
        }

    }


    public class Active_Test
    {
        private MessageHeader _Header;

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public Active_Test(uint Sequence_Id)
        {
            this._Header = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test, Sequence_Id);
        }

        public byte[] ToBytes()
        {
            return this._Header.ToBytes();
        }

        public override string ToString()
        {
            return this._Header.ToString();

        }
    }


    public class Active_Test_Resp
    {
        private MessageHeader _Header;
        //private byte _Reserved;

        //public byte Reserved
        //{
        //    get
        //    {
        //        return this._Reserved;
        //    }
        //}

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

      //  public const int BodyLength = 1;

        public Active_Test_Resp(uint Sequence_Id)
        {
         //   this._Reserved = 1;
            this._Header = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test_Resp, Sequence_Id);


        }

        public Active_Test_Resp(byte[] bytes)
        {
            //header
            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            this._Header = new MessageHeader(buffer);
        }

 

        public byte[] ToBytes()
        {
            return this._Header.ToBytes();
        }
        public override string ToString()
        {
            return this._Header.ToString();
        }

    }


    public class Query
    {
        private MessageHeader _Header;

        private string _QueryTime; // 8 Octet String 时间YYYYMMDD(精确至日)。
        private uint _QueryType; // 1 Unsigned Integer 查询类别:
        //   0:总数查询;
        //   1:按业务类型查询。
        private string _QueryCode; // 10 Octet String 查询码。

        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public string QueryTime
        {
            get
            {
                return this._QueryTime;
            }
        }

        public uint QueryType
        {
            get
            {
                return this._QueryType;
            }
        }

        public string QueryCode
        {
            get
            {
                return this._QueryCode;
            }
        }


        public const int BodyLength = 8 + 1 + 10;

        public Query
         (
          DateTime Time
          , uint Query_Type
          , string Query_Code
          , uint Sequence_Id
         )
        {
            this._QueryTime = Util.Get_YYYYMMDD_String(Time);
            this._QueryType = Query_Type;
            this._QueryCode = Query_Code;
            this._Header = new MessageHeader((uint)(MessageHeader.Length + BodyLength), SMGP3_RequestId.Query, Sequence_Id);
        }

        public byte[] ToBytes()
        {
            int i = 0;
            byte[] bytes = new byte[MessageHeader.Length + BodyLength];
            //header

            byte[] buffer = new byte[MessageHeader.Length];
            buffer = this._Header.ToBytes();
            buffer.CopyTo(bytes, 0);

            //Time 8
            i += MessageHeader.Length;
            buffer = new byte[10];
            buffer = Encoding.ASCII.GetBytes(this._QueryTime);
            buffer.CopyTo(bytes, i);

            //Query_Type 1
            i += 8;
            bytes[i++] = (byte)this._QueryType;

            //Query_Code 10
            buffer = new byte[10];
            buffer = Encoding.ASCII.GetBytes(this._QueryCode);
            buffer.CopyTo(bytes, i);

            return bytes;
        }
        public override string ToString()
        {
            return "[/r/n"
             + this._Header.ToString() + "/r/n"
             + string.Format
              (
               "/tMessageBody:"
               + "/r/n/t/tQueryCode: {0}"
               + "/r/n/t/tQueryType: {1}"
               + "/r/n/t/tQueryTime: {2}"
               + "/r/n]"
               , this._QueryCode
               , this._QueryType
               , this._QueryTime
              )
             + "/r/n]";
        }
    }


    public class Query_Resp
    {
        public MessageHeader Header
        {
            get
            {
                return this._Header;
            }
        }

        public string QueryTime
        {
            get
            {
                return this._QueryTime;
            }
        }

        public uint QueryType
        {
            get
            {
                return this._QueryType;
            }
        }

        public string QueryCode
        {
            get
            {
                return this._QueryCode;
            }
        }

        public uint Mt_TlMsg
        {
            get
            {
                return this._MT_TLMsg;
            }
        }

        public uint Mt_Tlusr
        {
            get
            {
                return this._MT_Tlusr;
            }
        }

        public uint Mt_Scs
        {
            get
            {
                return this._MT_Scs;
            }
        }

        public uint MT_WT
        {
            get
            {
                return this._MT_WT;
            }
        }

        public uint MT_FL
        {
            get
            {
                return this._MT_FL;
            }
        }

        public uint MO_Scs
        {
            get
            {
                return this._MO_Scs;
            }
        }

        public uint MO_WT
        {
            get
            {
                return this._MO_WT;
            }
        }

        public uint MO_FL
        {
            get
            {
                return this._MO_FL;
            }
        }

        private MessageHeader _Header;
        private string _QueryTime; // 8 Octet String 时间(精确至日)。
        private uint _QueryType; // 1 Unsigned Integer 查询类别:
        //   0:总数查询;
        //   1:按业务类型查询。
        private string _QueryCode; // 10 Octet String 查询码。
        private uint _MT_TLMsg; // 4 Unsigned Integer 从SP接收信息总数。
        private uint _MT_Tlusr; // 4 Unsigned Integer 从SP接收用户总数。
        private uint _MT_Scs; // 4 Unsigned Integer 成功转发数量。
        private uint _MT_WT; // 4 Unsigned Integer 待转发数量。
        private uint _MT_FL; // 4 Unsigned Integer 转发失败数量。
        private uint _MO_Scs; // 4 Unsigned Integer 向SP成功送达数量。
        private uint _MO_WT; // 4 Unsigned Integer 向SP待送达数量。
        private uint _MO_FL; // 4 Unsigned Integer 向SP送达失败数量。

        public const int BodyLength = 8 // Octet String 时间(精确至日)。
           + 1 // Unsigned Integer 查询类别:
            //  0:总数查询;
            //  1:按业务类型查询。
           + 10 // Octet String 查询码。
           + 4 // Unsigned Integer 从SP接收信息总数。
           + 4 // Unsigned Integer 从SP接收用户总数。
           + 4 // Unsigned Integer 成功转发数量。
           + 4 // Unsigned Integer 待转发数量。
           + 4 // Unsigned Integer 转发失败数量。
           + 4 // Unsigned Integer 向SP成功送达数量。
           + 4 // Unsigned Integer 向SP待送达数量。
           + 4; // Unsigned Integer 向SP送达失败数量。

        public Query_Resp(byte[] bytes)
        {
            int i = 0;
            //header 12
            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            this._Header = new MessageHeader(buffer);

            //Time 8
            i += MessageHeader.Length;
            buffer = new byte[8];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            this._QueryTime = Encoding.ASCII.GetString(buffer);

            //Query_Type 1
            i += 8;
            this._QueryType = (uint)bytes[i++];

            //Query_Code 10
            buffer = new byte[10];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            this._QueryCode = Encoding.ASCII.GetString(buffer);

            //MT_TLMsg 4
            i += 10;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MT_TLMsg = BitConverter.ToUInt32(buffer, 0);

            //MT_Tlusr 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MT_Tlusr = BitConverter.ToUInt32(buffer, 0);

            //MT_Scs 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MT_Scs = BitConverter.ToUInt32(buffer, 0);

            //MT_WT 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MT_WT = BitConverter.ToUInt32(buffer, 0);

            //MT_FL 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MT_FL = BitConverter.ToUInt32(buffer, 0);

            //MO_Scs 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MO_Scs = BitConverter.ToUInt32(buffer, 0);

            //MO_WT 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MO_WT = BitConverter.ToUInt32(buffer, 0);

            //MO_FL 4
            i += 4;
            buffer = new byte[4];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._MO_FL = BitConverter.ToUInt32(buffer, 0);
        }

        public override string ToString()
        {
            return "[/r/n"
             + this._Header.ToString() + "/r/n"
             + string.Format
              (
               "/tMessageBody:"
               + "/r/n/t/tBodyLength: {0}"
               + "/r/n/t/tMO_FL: {1}"
               + "/r/n/t/tMO_Scs: {2}"
               + "/r/n/t/tMO_WT: {3}"
               + "/r/n/t/tMT_FL: {4}"
               + "/r/n/t/tMT_Scs: {5}"
               + "/r/n/t/tMT_TLMsg: {6}"
               + "/r/n/t/tMT_Tlusr: {7}"
               + "/r/n/t/tMT_WT: {8}"
               + "/r/n/t/tQueryCode: {9}"
               + "/r/n/t/tQueryType: {10}"
               + "/r/n/t/tQueryTime: {11}"

               , Query_Resp.BodyLength
               , this._MO_FL
               , this._MO_Scs
               , this._MO_WT
               , this._MT_FL
               , this._MT_Scs
               , this._MT_TLMsg
               , this._MT_Tlusr
               , this._MT_WT
               , this._QueryCode
               , this._QueryType
               , this._QueryTime
              )
                  + "/r/n]";
        }
    }


    public class MsgContent 
    {
        public const int BodyLength = 10 + 3+3 + 10 + 10 + 7 + 3+20;

        private string _MsgID; // 10 Octet String 信息标识。SP提交短信(CMPP_SUBMIT)操作时,与SP相连的ISMG产生的Msg_Id。
        private string _Sub;    //3
        private string _Dlvrd;  //3
        private string _Submit_date;    //10
        private string _Done_date;  //10
        private string _Stat; // 7
        private string _Err;  //3
        private string _Txt;  //3+17

        //public MsgContent(string msgcontent)
        //{
        //    string s=null;
        //   // msgcontent.
        //    //s = s.Substring(0, s.IndexOf('/0'));
        //    int startIndex=msgcontent.IndexOf("id:");
        //    int lastIndex=msgcontent.IndexOf("sub:");
        //    if (startIndex >= 0 && lastIndex > startIndex)
        //        s = msgcontent.Substring(startIndex, lastIndex);

        //    int i = 0;
        //    byte[] bytes=Encoding.ASCII.GetBytes(s);
        //    byte[] buffer = new byte[10];
        //    Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
        //    Array.Reverse(buffer);
        //    this._MsgID = BitConverter.ToUInt32(buffer, 0);


        //    startIndex = lastIndex;
        //    lastIndex = msgcontent.IndexOf("dlvrd:");
        //    if (startIndex >= 0 && lastIndex > startIndex)
        //        s = msgcontent.Substring(startIndex, lastIndex);
        //    this._Sub = s;


        //    startIndex = lastIndex;
        //    lastIndex = msgcontent.IndexOf("dlvrd:");
        //    if (startIndex >= 0 && lastIndex > startIndex)
        //        s = msgcontent.Substring(startIndex, lastIndex);
        //    this._Sub = s;
        //}


        public MsgContent(byte[] bytes)
        {
            if (bytes.Length >= BodyLength)
            {

                ///“id:IIIIIIIIII sub:SSS dlvrd:DDD Submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E Text:……

                string tag="";
                int i = 0;
               
                //_MsgID 10
                tag="id:";
                i += tag.Length;
                byte[] buffer = new byte[10];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._MsgID = System.BitConverter.ToString(buffer);
              //  string test = System.BitConverter.ToString(buffer);
              //  System.Console.WriteLine("MsgContent=" + test);

                //Array.Reverse(buffer);
                //this._MsgID = BitConverter.ToUInt32(buffer, 0);

 

                //_Sub 3
                i += 10;
                tag = "sub:";
                i += tag.Length;
                buffer = new byte[3];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Sub = Encoding.ASCII.GetString(buffer);

                //_Dlvrd 3
                i += 3;
                tag = " dlvrd:";
                i += tag.Length;
                buffer = new byte[3];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Dlvrd = Encoding.ASCII.GetString(buffer);


                //_Submit_date 10
                i += 3;
                tag = " Submit date:";
                i += tag.Length;
                buffer = new byte[10];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Submit_date = Encoding.ASCII.GetString(buffer);

                //_Done_date 10
                i += 10;
                tag = " done date:";
                i += tag.Length;
                buffer = new byte[10];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Done_date = Encoding.ASCII.GetString(buffer);

                //_Stat 7
                i += 10;
                tag = " stat:";
                i += tag.Length;
                buffer = new byte[7];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Stat = Encoding.ASCII.GetString(buffer);

                //_Err 3
                i += 7;
                tag = " err:";
                i += tag.Length;
                buffer = new byte[3];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Err = Encoding.ASCII.GetString(buffer);

                //_Txt 20
                i += 3;
                tag = " txt:";
                i += tag.Length;
                buffer = new byte[bytes.Length - i];
                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                this._Txt = Encoding.ASCII.GetString(buffer);


                //i += 3;
                //buffer = new byte[bytes.Length-i];
                //Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                //this._Txt = Encoding.ASCII.GetString(buffer);
            }
        }


        /// <summary>
        /// 状态报告对应原短消息的MsgID
        /// </summary>
        public string MsgID
        {
            get { return _MsgID; }
        }


        /// <summary>
        /// 取缺省值001
        /// </summary>
        public string Sub
        {
            get { return _Sub; }
        }


        /// <summary>
        /// 取缺省值001
        /// </summary>
        public string Dlvrd
        {
            get { return _Dlvrd; }
        }


        /// <summary>
        /// 短消息提交时间(格式:年年月月日日时时分分,例如010331200000)
        /// </summary>
        public string Submit_date
        {
            get { return _Submit_date; }
        }

        /// <summary>
        /// 短消息下发时间(格式:年年月月日日时时分分,例如010331200000)
        /// </summary>
        public string Done_date
        {
            get { return _Done_date; }
        }


        /// <summary>
        /// 短消息的最终状态
        /// </summary>
        public string Stat
        {
            get { return _Stat; }
        }

        /// <summary>
        /// 错误代码表
        /// </summary>
        public string Err
        {
            get { return _Err; }
        }

        /// <summary>
        ///
        /// </summary>
        public string Txt
        {
            get { return _Txt; }
        }


        public override string ToString()
        {
            return string.Format
              (
               "[/r/nMessageBody:"
               + "/r/n/tBodyLength: {0}"
               + "/r/n/tMsgID: {1}"
               + "/r/n/tSub: {2}"
               + "/r/n/tDlvrd: {3}"
               + "/r/n/tSubmit_date: {4}"
               + "/r/n/tDone_date: {5}"
               + "/r/n/tStat: {6}"
               + "/r/n/tErr: {7}"
               + "/r/n/tTxt: {8}"
               + "/r/n]"
               , MsgContent.BodyLength
               , this._MsgID
               , this._Sub
               , this._Dlvrd
               , this._Submit_date
               , this._Done_date
               , this._Stat
               , this._Err
               , this._Txt
              );
        }


    }


    public class TlvId
    {
        public static short TP_pid = 0x0001;
        public static short TP_udhi = 0x0002;
        public static short LinkID = 0x0003;
        public static short ChargeUserType = 0x0004;
        public static short ChargeTermType = 0x0005;
        public static short ChargeTermPseudo = 0x0006;
        public static short DestTermType = 0x0007;
        public static short DestTermPseudo = 0x0008;
        public static short PkTotal = 0x0009;
        public static short PkNumber = 0x000A;
        public static short SubmitMsgType = 0x000B;
        public static short SPDealReslt = 0x000C;
        public static short SrcTermType = 0x000D;
        public static short SrcTermPseudo = 0x000E;
        public static short NodesCount = 0x000F;
        public static short MsgSrc = 0x0010;
        public static short SrcType = 0x0011;
        public static short Mserviceid = 0x0012;
    }


    public class Tlv
    {
        public short Tag;
        public short Length;
        public String Value;
        public byte[] TlvBuf;

        public Tlv(short tag, string value)
        {
            this.Tag = tag;
            this.Length = (short)value.Length;
            this.Value = value;
            if (tag == TlvId.Mserviceid || tag == TlvId.MsgSrc
                    || tag == TlvId.SrcTermPseudo || tag == TlvId.DestTermPseudo
                    || tag == TlvId.ChargeTermPseudo || tag == TlvId.LinkID)
            {
                //参数为oct string
                int i = 0;
                this.TlvBuf = new byte[4 + this.Length];

                //Tag  2
                byte[] buffer = BitConverter.GetBytes((short)Tag);
                Array.Reverse(buffer);
                buffer.CopyTo(TlvBuf, i);

                //Length  2
                i += 2;
                buffer = BitConverter.GetBytes(Length);
                Array.Reverse(buffer);
                buffer.CopyTo(TlvBuf, i);

                //Value Length
                i += 2;
                buffer = Encoding.ASCII.GetBytes(this.Value);
                Buffer.BlockCopy(buffer, 0, TlvBuf, i, buffer.Length);

            }
            else
            {
                int i = 0;
                this.TlvBuf = new byte[4 + 1];

                //Tag 2
                byte[] buffer = BitConverter.GetBytes((short)Tag);
                Array.Reverse(buffer);
                buffer.CopyTo(TlvBuf, i);

                //Length  2
                i += 2;
                buffer = BitConverter.GetBytes(Length);
                Array.Reverse(buffer);
                buffer.CopyTo(TlvBuf, i);

                //Value 1
                i += 2;
                uint tmp = 0;
                uint.TryParse(value, out tmp);
                TlvBuf[i] = (byte)tmp;

            }

        }
    }

 

}

//------------------------------------------------------------------------------

//文件StateDictionary.cs

//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace AsiaINFO.SMS.SMGP3
{
    /// <summary>
    /// 状态字典
    /// </summary>
    public class StateDictionary
    {

        /// <summary>
        /// Status 请求返回结果。响应包用来向请求包返回成功信息或者失败原因。
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public static string stateRespDictionary(uint state)
        {
            string result = "结果:";
            switch (state)
            {
                case 0: result += "成功"; break;
                case 1: result += "系统忙"; break;
                case 2: result += "超过最大连接数"; break;
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                case 9: result += "保留"; break;
                case 10: result +="消息结构错";break;
                case 11: result +="命令字错";break;
                case 12: result +="序列号重复";break;
                case 13:
                case 14:
                case 15:
                case 16:
                case 17:
                case 18:
                case 19: result +="保留";break;
                case 20: result +="IP 地址错";break;
                case 21: result +="认证错";break;
                case 22: result +="版本太高";break;
                case 23:
                case 24:
                case 25:
                case 26:
                case 27:
                case 28:
                case 29: result +="保留";break;
                case 30: result +="非法消息类型(MsgType)";break;
                case 31: result +="非法优先级(Priority)";break;
                case 32: result +="非法资费类型(FeeType)";break;
                case 33: result +="非法资费代码(FeeCode)";break;
                case 34: result +="非法短消息格式(MsgFormat)";break;
                case 35: result +="非法时间格式";break;
                case 36: result +="非法短消息长度(MsgLength)";break;
                case 37: result +="有效期已过";break;
                case 38: result +="非法查询类别(QueryType)";break;
                case 39: result +="路由错误";break;
                case 40: result +="非法包月费/封顶费(FixedFee)";break;
                case 41: result +="非法更新类型(UpdateType";break;
                case 42: result +="非法路由编号(RouteId)";break;
                case 43: result +="非法服务代码(ServiceId)";break;
                case 44: result +="非法有效期(ValidTime)";break;
                case 45: result +="非法定时发送时间(AtTime)";break;
                case 46: result +="非法发送用户号码(SrcTermId)";break;
                case 47: result +="非法接收用户号码(DestTermId)";break;
                case 48: result +="非法计费用户号码(ChargeTermId)";break;
                case 49: result +="非法SP 服务代码(SPCode)";break;
                case 50:
                case 51:
                case 52:
                case 53:
                case 54:
                case 55: result +=" 其它用途";break;
                case 56: result +="非法源网关代码(SrcGatewayID)";break;
                case 57: result +="非法查询号码(QueryTermID)";break;
                case 58: result +="没有匹配路由";break;
                case 59: result +="非法SP 类型(SPType)";break;
                case 60: result +="非法上一条路由编号(LastRouteID)";break;
                case 61: result +="非法路由类型(RouteType)";break;
                case 62: result +="非法目标网关代码(DestGatewayID)";break;
                case 63: result +="非法目标网关IP(DestGatewayIP)";break;
                case 64: result +="非法目标网关端口(DestGatewayPort)";break;
                case 65: result +="非法路由号码段(TermRangeID)";break;
                case 66: result +="非法终端所属省代码(ProvinceCode)";break;
                case 67: result +="非法用户类型(UserType)";break;
                case 68: result +="本节点不支持路由更新";break;
                case 69: result +="非法SP 企业代码(SPID)";break;
                case 70: result +="非法SP 接入类型(SPAccessType)";break;
                case 71: result +="路由信息更新失败";break;
                case 72: result +="非法时间戳(Time)";break;
                case 73: result += "非法业务代码(MServiceID)"; break;
                case 74: result += "SP 禁止下发时段"; break;
                case 75: result += "SP 发送超过日流量"; break;
                case 76: result += "SP 帐号过有效期"; break;
                case 112:
                case 113:
                case 114:
                case 115:
                case 116: result += "其它用途"; break;
                default: result += "未知错误" ; break;
            }
            return result;

 

        }
    }
}

 

//------------------------------------------------------------------------------

//文件SyncEvents.cs

//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace AsiaINFO.SMS.SMGP3
{
    /// <summary>
    /// 同步信号量
    /// </summary>
    public class SyncEvents
    {
        public SyncEvents()
        {
            _newItemEvent = new AutoResetEvent(false);
            _exitThreadEvent = new ManualResetEvent(false);
            _eventArray = new WaitHandle[2];
            _eventArray[0] = _newItemEvent;
            _eventArray[1] = _exitThreadEvent;
        }

        /// <summary>
        /// 退出信号
        /// </summary>
        public EventWaitHandle ExitThreadEvent
        {
            get { return _exitThreadEvent; }
        }

        /// <summary>
        /// 收到数据信号
        /// </summary>
        public EventWaitHandle NewItemEvent
        {
            get { return _newItemEvent; }
        }

        public WaitHandle[] EventArray
        {
            get { return _eventArray; }
        }

        private EventWaitHandle _newItemEvent;

        private EventWaitHandle _exitThreadEvent;
        private WaitHandle[] _eventArray;
    }
}

 

 

//------------------------------------------------------------------------------

//文件Util.cs

//------------------------------------------------------------------------------

 

using System;
using System.Net.Sockets;

namespace AsiaINFO.SMS.SMGP3
{
    public class Util
    {
        //private static object _SyncLockObject = new object();

        public static string Get_MMDDHHMMSS_String(DateTime dt)
        {
            string s = dt.Month.ToString().PadLeft(2, '0');
            s += dt.Day.ToString().PadLeft(2, '0');
            s += dt.Hour.ToString().PadLeft(2, '0');
            s += dt.Minute.ToString().PadLeft(2, '0');
            s += dt.Second.ToString().PadLeft(2, '0');
            return s;
        }

        public static string Get_YYYYMMDD_String(DateTime dt)
        {
            string s = dt.Year.ToString().PadLeft(4, '0');
            s += dt.Month.ToString().PadLeft(2, '0');
            s += dt.Day.ToString().PadLeft(2, '0');
            return s;
        }

        internal static void WriteToStream(byte[] bytes, NetworkStream Stream)
        {
            if (Stream.CanWrite)
            {
                //lock (_SyncLockObject)
                //{
                    Stream.Write(bytes, 0, bytes.Length);
                //}
            }
        }

        internal static byte[] ReadFromStream(int Length, NetworkStream Stream)
        {
            byte[] bytes = null;
            if (Stream.CanRead)
            {
                if (Stream.DataAvailable)
                {
                    bytes = new byte[Length];
                    int r = 0;
                    int l = 0;
                    //lock (_SyncLockObject)
                    {
                        while (l < Length)
                        {
                            r = Stream.Read(bytes, l, Length - l);
                            l += r;
                        }
                    }
                }
            }
            return bytes;
        }
    }
}

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值