.Net/C# 实现 中国移动 CMPP v3.0 ISMG SP 收发短信的 SP 客户端 (第2版) (CMPP SP Client)




/*

.Net/C# 实现 中国移动 CMPP v3.0 ISMG <-> SP 收发短信的 SP 客户端 (第2版)(CMPP SP Client)

增加了 CMPP Client 类

本程序严格按

《中国移动通信企业标准》之《中国移动通信互联网短信网关接口协议(China Mobile Point to Point)》(版本号: 3.0.0)

即: CMPP v3.0.0

http://www.spzone.net/protocol/CMPPV3.0.rar

文档,实现了下面消息的定义及其相关协议级交互:

8.4 业务提供商 (SP) 与互联网短信网关 (ISMG) 间的消息定义 8

8.4.1 SP 请求连接到 ISMG(CMPP_CONNECT) 操作 8

8.4.1.1 CMPP_CONNECT 消息定义 (SP -> ISMG) 8

8.4.1.2 CMPP_CONNECT_RESP消息定义 (ISMG -> SP) 9

8.4.2 SP 或 ISMG 请求拆除连接 (CMPP_TERMINATE)操作 9

8.4.2.1 CMPP_TERMINATE 消息定义 (SP -> ISMG 或 ISMG -> SP) 9

8.4.2.2 CMPP_TERMINATE_RESP 消息定义 (SP -> ISMG 或 ISMG -> SP) 10

8.4.3 SP 向 ISMG提交短信 (CMPP_SUBMIT) 操作 10

8.4.3.1 CMPP_SUBMIT 消息定义 (SP -> ISMG) 10

8.4.3.2 CMPP_SUBMIT_RESP 消息定义 (ISMG -> SP) 11

8.4.5 ISMG 向 SP 送交短信 (CMPP_DELIVER) 操作 13

8.4.5.1 CMPP_DELIVER 消息定义 (ISMG -> SP) 13

8.4.5.2 CMPP_DELIVER_RESP 消息定义 (SP -> ISMG) 16

8.4.7 链路检测 (CMPP_ACTIVE_TEST) 操作 17

8.4.7.1 CMPP_ACTIVE_TEST定义 (SP -> ISMG 或 ISMG <- SP) 17

8.4.7.2 CMPP_ACTIVE_TEST_RESP定义 (SP -> ISMG 或 ISMG <- SP) 17

可采用《中国移动通信 CMPP v3.0 短消息网关模拟器 v1.10》进行测试:

下载于: 《北京风起水流软件工作室》

http://www.zealware.com/download/cmpp3smg.rar

《中国移动通信 CMPP v3.0 短消息网关模拟器 v1.10》

http://tech.spforum.net/uploadfile/2006426181749702.rar

本程序以熟悉理解 CMPP 3.0 协议为主要目的,只将 "消息定义" 对象化,其相关协议级交互并未作更深层次的 OO!

也暂无任何错误处理程序!

消息定义的所有字段名称及其数据类型均与上述之 CMPP v3.0.0 文档完全一致!

其间参阅过 shanhe@CSDN or yexiong@cnBlogs 大作(在此鸣谢):

http://blog.csdn.net/shanhe/archive/2004/07/19/45383.aspx

http://cnblogs.com/yexiong/articles/115330.aspx

但其中有些消息定义字节错位,因此不能正常交互?!且对象化层次较高,不利于理解协议本身!

遂自己动手,丰衣足食,实现部分主要协议(SP 收发短信):

playyuer㊣Microshaoft.com Invent.

*/

namespace Microshaoft

{

    using System;

    using System.Net.Sockets;

    public class Utility

    {

        public static string BytesArrayToHexString(byte[] data)

        {

            return BitConverter.ToString(data).Replace("-", "");

        }

        public static byte[] HexStringToBytesArray(string text)

        {

            text = text.Replace(" ", "");

            int l = text.Length;

            byte[] buffer = new byte[l / 2];

            for (int i = 0; i < l; i += 2)

            {

                buffer[i / 2] = Convert.ToByte(text.Substring(i, 2), 16);

            }

            return buffer;

        }

        //private static object _SyncLockObject = new object();

        public static string Get_MMDDHHMMSS_String(DateTime dt)

        {

            return DateTime.Now.ToString("MMddhhmmss");

        }

        public static string Get_YYYYMMDD_String(DateTime dt)

        {

            return DateTime.Now.ToString("yyyyMMdd");

        }

        internal static void WriteToStream(byte[] bytes, NetworkStream Stream)

        {

            if (Stream.CanWrite)

            {

                //lock (_SyncLockObject)

                {

                    Stream.Write(bytes, 0, bytes.Length);

                }

            }

        }

        internal static byte[] ReadStreamToBytes(int Length, NetworkStream Stream)

        {

            byte[] bytes = null;

            if (Stream.CanRead)

            {

                if (Stream.DataAvailable)

                {

                    bytes = new byte[Length];

                    int l = 0;

                    //lock (_SyncLockObject)

                    {

                        while (l < Length)

                        {

                            int r;

                            r = Stream.Read(bytes, l, Length - l);

                            l += r;

                        }

                    }

                }

            }

            return bytes;

        }

    }

}

//CMPP 消息定义

namespace Microshaoft.CMPP.Messages

{

    using System;

    using System.Text;

    using System.Security.Cryptography;

    public enum CMPP_Command_Id : uint

    {

        CMPP_CONNECT = 0x00000001 //请求连接

        ,

        CMPP_CONNECT_RESP = 0x80000001 //请求连接应答

            ,

        CMPP_TERMINATE = 0x00000002 //终止连接

            ,

        CMPP_TERMINATE_RESP = 0x80000002 //终止连接应答

            ,

        CMPP_SUBMIT = 0x00000004 //提交短信

            ,

        CMPP_SUBMIT_RESP = 0x80000004 //提交短信应答

            ,

        CMPP_DELIVER = 0x00000005 //短信下发

            ,

        CMPP_DELIVER_RESP = 0x80000005 //下发短信应答

            ,

        CMPP_QUERY = 0x00000006 //发送短信状态查询

            ,

        CMPP_QUERY_RESP = 0x80000006 //发送短信状态查询应答

            ,

        CMPP_CANCEL = 0x00000007 //删除短信

            ,

        CMPP_CANCEL_RESP = 0x80000007 //删除短信应答

            ,

        CMPP_ACTIVE_TEST = 0x00000008 //激活测试

            ,

        CMPP_ACTIVE_TEST_RESP = 0x80000008 //激活测试应答

            ,

        CMPP_FWD = 0x00000009 //消息前转

            ,

        CMPP_FWD_RESP = 0x80000009 //消息前转应答

            ,

        CMPP_MT_ROUTE = 0x00000010 //MT路由请求

            ,

        CMPP_MT_ROUTE_RESP = 0x80000010 //MT路由请求应答

            ,

        CMPP_MO_ROUTE = 0x00000011 //MO路由请求

            ,

        CMPP_MO_ROUTE_RESP = 0x80000011 //MO路由请求应答

            ,

        CMPP_GET_MT_ROUTE = 0x00000012 //获取MT路由请求

            ,

        CMPP_GET_MT_ROUTE_RESP = 0x80000012 //获取MT路由请求应答

            ,

        CMPP_MT_ROUTE_UPDATE = 0x00000013 //MT路由更新

            ,

        CMPP_MT_ROUTE_UPDATE_RESP = 0x80000013 //MT路由更新应答

            ,

        CMPP_MO_ROUTE_UPDATE = 0x00000014 //MO路由更新

            ,

        CMPP_MO_ROUTE_UPDATE_RESP = 0x80000014 //MO路由更新应答

            ,

        CMPP_PUSH_MT_ROUTE_UPDATE = 0x00000015 //MT路由更新

            ,

        CMPP_PUSH_MT_ROUTE_UPDATE_RESP = 0x80000015 //MT路由更新应答

            ,

        CMPP_PUSH_MO_ROUTE_UPDATE = 0x00000016 //MO路由更新

            ,

        CMPP_PUSH_MO_ROUTE_UPDATE_RESP = 0x80000016 //MO路由更新应答

            ,

        CMPP_GET_MO_ROUTE = 0x00000017 //获取MO路由请求

            , CMPP_GET_MO_ROUTE_RESP = 0x80000017 //获取MO路由请求应答

    }

    public class MessageHeader //消息头

    {

        public const int Length = 4 + 4 + 4;

        public CMPP_Command_Id Command_Id

        {

            get

            {

                return _Command_Id;

            }

        }

        public uint Sequence_Id

        {

            get

            {

                return _Sequence_Id;

            }

        }

        public uint Total_Length

        {

            get

            {

                return _Total_Length;

            }

        }

        private uint _Total_Length; // 4 Unsigned Integer 消息总长度(含消息头及消息体)

        private CMPP_Command_Id _Command_Id; // 4 Unsigned Integer 命令或响应类型

        private uint _Sequence_Id; // 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)

        public MessageHeader

          (

           uint Total_Length

           , CMPP_Command_Id Command_Id

           , uint Sequence_Id

          ) //发送前

        {

            _Total_Length = Total_Length;

            _Command_Id = Command_Id;

            _Sequence_Id = Sequence_Id;

        }

        public MessageHeader(byte[] bytes)

        {

            byte[] buffer = new byte[4];

            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Total_Length = BitConverter.ToUInt32(buffer, 0);

            Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Command_Id = (CMPP_Command_Id)BitConverter.ToUInt32(buffer, 0);

            Buffer.BlockCopy(bytes, 8, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Sequence_Id = BitConverter.ToUInt32(buffer, 0);

        }

        public byte[] ToBytes()

        {

            byte[] bytes = new byte[MessageHeader.Length];

            byte[] buffer = BitConverter.GetBytes(_Total_Length);

            Array.Reverse(buffer);

            Buffer.BlockCopy(buffer, 0, bytes, 0, 4);

            buffer = BitConverter.GetBytes((uint)_Command_Id);

            Array.Reverse(buffer);

            Buffer.BlockCopy(buffer, 0, bytes, 4, 4);

            buffer = BitConverter.GetBytes(_Sequence_Id);

            Array.Reverse(buffer);

            Buffer.BlockCopy(buffer, 0, bytes, 8, 4);

            return bytes;

        }

        public override string ToString()

        {

            return string.Format

              (

               "\tMessageHeader:{0}Command_Id: {1}{0}Sequence_Id: {2}{0}Total_Length: {2}"

               , "\r\n\t\t"

               , _Command_Id

               , _Sequence_Id

               , _Total_Length

              );

        }

    }

    public class CMPP_CONNECT //: CMPP_Request

    {

        public const int BodyLength = 6 + 16 + 1 + 4;

        private string _Source_Addr; // 6 Octet String 源地址,此处为SP_Id,即SP的企业代码。

        private string _Password;

        private byte[] _AuthenticatorSource; // 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:

        // AuthenticatorSource =

        // MD5(Source_Addr+9 字节的0 +shared secret+timestamp)

        // Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。

        private uint _Version; // 1 Unsigned Integer 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号),对于3.0的版本,高4bit为3,低4位为0

        private uint _Timestamp; // 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。

        private MessageHeader _Header;

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public byte[] AuthenticatorSource

        {

            get

            {

                return _AuthenticatorSource;

            }

        }

        public CMPP_CONNECT

         (

          string Source_Addr

          , string Password

          , DateTime Timestamp

          , uint Version

          , uint Sequence_Id

         )

        {

            _Header = new MessageHeader

                (

                 MessageHeader.Length + BodyLength

                 , CMPP_Command_Id.CMPP_CONNECT

                 , Sequence_Id

                );

            _Source_Addr = Source_Addr;

            _Password = Password;

            string s = Utility.Get_MMDDHHMMSS_String(Timestamp);

            _Timestamp = UInt32.Parse(s);

            byte[] buffer = new byte[6 + 9 + _Password.Length + 10];

            Encoding.ASCII.GetBytes(_Source_Addr).CopyTo(buffer, 0);

            Encoding.ASCII.GetBytes(_Password).CopyTo(buffer, 6 + 9);

            Encoding.ASCII.GetBytes(s).CopyTo(buffer, 6 + 9 + _Password.Length);

            _AuthenticatorSource = new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);

            _Version = Version;

        }

        public byte[] ToBytes()

        {

            int i = 0;

            byte[] bytes = new byte[MessageHeader.Length + BodyLength];

            //header 12

            byte[] buffer = _Header.ToBytes();

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //Source_Addr 6

            i += MessageHeader.Length;

            buffer = Encoding.ASCII.GetBytes(_Source_Addr);

            Buffer.BlockCopy(buffer, 0, bytes, i, 6);

            //AuthenticatorSource 16

            i += 6;

            buffer = _AuthenticatorSource;

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //16

            //version 1

            i += 16;

            bytes[i++] = (byte)_Version; //版本

            //Timestamp

            buffer = BitConverter.GetBytes(_Timestamp);

            Array.Reverse(buffer);

            buffer.CopyTo(bytes, i);

            return (bytes);

        }

        public override string ToString()

        {

            return "[\r\n"

               + _Header.ToString() + "\r\n"

               + "\t"

               + string.Format

                 (

                  "MessageBody:"

                  + "{0}AuthenticatorSource: {1}"

                  + "{0}Password: {2}"

                  + "{0}Source_Addr: {3}"

                  + "{0}Version: {4}"

                  , "\r\n\t\t"

                  , Utility.BytesArrayToHexString(_AuthenticatorSource)

                  , _Password

                  , _Source_Addr

                  , _Timestamp

                  , _Version

                 )

               + "\r\n]";

        }

    }

    public class CMPP_CONNECT_RESP //: CMPP_Response

    {

        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 _Version; // 1 Unsigned Integer 服务器支持的最高版本号,对于3.0的版本,高4bit为3,低4位为0

        public byte[] AuthenticatorISMG

        {

            get

            {

                return _AuthenticatorISMG;

            }

        }

        public uint Status

        {

            get

            {

                return _Status;

            }

        }

        public uint Version

        {

            get

            {

                return _Version;

            }

        }

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public CMPP_CONNECT_RESP(byte[] bytes)

        {

            //header 12

            int i = 0;

            byte[] buffer = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

            _Header = new MessageHeader(buffer);

            //status 4

            i += MessageHeader.Length;

            buffer = new byte[4];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Status = BitConverter.ToUInt32(buffer, 0);

            //AuthenticatorISMG 16

            i += 4;

            _AuthenticatorISMG = new byte[16];

            Buffer.BlockCopy

               (

                bytes

                , MessageHeader.Length + 4

                , _AuthenticatorISMG

                , 0

                , _AuthenticatorISMG.Length

               );

            //version

            i += 16;

            _Version = bytes[i];

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

               (

                "MessageBody:"

                + "{0}AuthenticatorISMG: {1}"

                + "{0}BodyLength: {2}"

                + "{0}Status: {3}"

                + "{0}Version: {4}"

                , "\r\n\t\t"

                , Utility.BytesArrayToHexString(_AuthenticatorISMG)

                , CMPP_CONNECT_RESP.BodyLength

                , _Status

                , _Version

               )

              + "\r\n]";

        }

    }

    public class CMPP_SUBMIT //: CMPP_Request

    {

        private int _BodyLength;

        //without _Dest_terminal_Id Msg_Content

        public const int FixedBodyLength = 8

                 + 1

                 + 1

                 + 1

                 + 1

                 + 10

                 + 1

                 + 32

                 + 1

                 + 1

                 + 1

                 + 1

                 + 6

                 + 2

                 + 6

                 + 17

                 + 17

                 + 21

                 + 1

            //+ 32*DestUsr_tl

                 + 1

                 + 1

            //+ Msg_length

                 + 20;

        private ulong _Msg_Id; // 8 Unsigned Integer 信息标识。

        private uint _Pk_total; // 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始。

        private uint _Pk_number; // 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始。

        private uint _Registered_Delivery; // 1 Unsigned Integer 是否要求返回状态确认报告:

        // 0:不需要;

        // 1:需要。

        private uint _Msg_level; // 1 Unsigned Integer 信息级别。

        private string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

        private uint _Fee_UserType; // 1 Unsigned Integer 计费用户类型字段:

        // 0:对目的终端MSISDN计费;

        // 1:对源终端MSISDN计费;

        // 2:对SP计费;

        // 3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。

        private string _Fee_terminal_Id; // 32 Octet String 被计费用户的号码,当Fee_UserType为3时该值有效,当Fee_UserType为0、1、2时该值无意义。

        private uint _Fee_terminal_type; // 1 Unsigned Integer 被计费用户的号码类型,0:真实号码;1:伪码。

        private uint _TP_pId; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9。

        private uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

        private uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

        // 0:ASCII串;

        // 3:短信写卡操作;

        // 4:二进制信息;

        // 8:UCS2编码;

        // 15:含GB汉字......

        private string _Msg_src; // 6 Octet String 信息内容来源(SP_Id)。

        private string _FeeType; // 2 Octet String 资费类别:

        // 01:对"计费用户号码"免费;

        // 02:对"计费用户号码"按条计信息费;

        // 03:对"计费用户号码"按包月收取信息费。

        private string _FeeCode; // 6 Octet String 资费代码(以分为单位)。

        private string _ValId_Time; // 17 Octet String 存活有效期,格式遵循SMPP3.3协议。

        private string _At_Time; // 17 Octet String 定时发送时间,格式遵循SMPP3.3协议。

        private string _Src_Id; // 21 Octet String 源号码。SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,该号码最终在用户手机上显示为短消息的主叫号码。

        private uint _DestUsr_tl; // 1 Unsigned Integer 接收信息的用户数量(小于100个用户)。

        private string[] _Dest_terminal_Id; // 32*DestUsr_tl Octet String 接收短信的MSISDN号码。

        private uint _Dest_terminal_type; // 1 Unsigned Integer 接收短信的用户的号码类型,0:真实号码;1:伪码。

        private uint _Msg_Length; // 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节),取值大于或等于0。

        private string _Msg_Content; // Msg_length Octet String 信息内容。

        private string _LinkID; // 20 Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

            set

            {

                _Header = value;

            }

        }

        private MessageHeader _Header;

        private uint _Sequence_Id;

        public CMPP_SUBMIT(uint Sequence_Id)

        {

            _Sequence_Id = Sequence_Id;

        }

        private byte[] _Msg_Content_Bytes;

        private void SetHeader()

        {

            //byte[] buf;

            switch (_Msg_Fmt)

            {

                case 8:

                    _Msg_Content_Bytes = Encoding.BigEndianUnicode.GetBytes(_Msg_Content);

                    break;

                case 15: //gb2312

                    _Msg_Content_Bytes = Encoding.GetEncoding("gb2312").GetBytes(_Msg_Content);

                    break;

                case 0: //ascii

                case 3: //短信写卡操作

                case 4: //二进制信息

                default:

                    _Msg_Content_Bytes = Encoding.ASCII.GetBytes(_Msg_Content);

                    break;

            }

            _Msg_Length = (uint)_Msg_Content_Bytes.Length;

            _BodyLength = (int)(FixedBodyLength + 32 * _Dest_terminal_Id.Length + _Msg_Length);

            _Header = new MessageHeader

                (

                 (uint)(MessageHeader.Length + _BodyLength)

                 , CMPP_Command_Id.CMPP_SUBMIT

                 , _Sequence_Id

                );

        }

        public byte[] ToBytes()

        {

            //Msg_Length Msg_Content

            int i = 0;

            byte[] bytes = new byte[MessageHeader.Length + _BodyLength];

            byte[] buffer = _Header.ToBytes();

            Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

            i += MessageHeader.Length;

            //Msg_Id //8 [12,19]

            buffer = new byte[8];

            buffer = BitConverter.GetBytes(_Msg_Id);

            Array.Reverse(buffer);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10 //[24,33]

            //_Pk_total

            i += 8;

            bytes[i++] = (byte)_Pk_total; //[20,20]

            bytes[i++] = (byte)_Pk_number; //[21,21]

            bytes[i++] = (byte)_Registered_Delivery; //[22,22]

            bytes[i++] = (byte)_Msg_level; //[23,23]

            //Service_Id

            buffer = Encoding.ASCII.GetBytes(_Service_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10 //[24,33]

            //Fee_UserType

            i += 10;

            bytes[i++] = (byte)_Fee_UserType; //[34,34]

            //Fee_terminal_Id

            buffer = Encoding.ASCII.GetBytes(_Fee_terminal_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //32 //[35,66]

            //Fee_terminal_type

            i += 32;

            bytes[i++] = (byte)_Fee_terminal_type; //[67,67]

            bytes[i++] = (byte)_TP_pId; //[68,68]

            bytes[i++] = (byte)_TP_udhi; //[69,69]

            bytes[i++] = (byte)_Msg_Fmt; //[70,70]

            //Msg_src

            buffer = Encoding.ASCII.GetBytes(_Msg_src);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[71,76]

            //FeeType

            i += 6;

            buffer = Encoding.ASCII.GetBytes(_FeeType);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //2 //[77,78]

            //FeeCode

            i += 2;

            buffer = Encoding.ASCII.GetBytes(_FeeCode);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[79,84]

            //ValId_Time

            i += 6;

            buffer = Encoding.ASCII.GetBytes(_ValId_Time);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[85,101]

            //At_Time

            i += 17;

            buffer = Encoding.ASCII.GetBytes(_At_Time);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[102,118]

            //Src_Id

            i += 17;

            buffer = Encoding.ASCII.GetBytes(_Src_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21 //[119,139]

            //DestUsr_tl

            i += 21;

            _DestUsr_tl = (uint)_Dest_terminal_Id.Length;

            bytes[i++] = (byte)_DestUsr_tl; //[140,140]

            //Dest_terminal_Id

            foreach (string s in _Dest_terminal_Id)

            {

                buffer = Encoding.ASCII.GetBytes(s);

                Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

                i += 32;

            }

            //Dest_terminal_type

            bytes[i++] = (byte)_Dest_terminal_type;

            //Msg_Length

            bytes[i++] = (byte)_Msg_Length;

            //Msg_Content

            //buffer = Encoding.

            Buffer.BlockCopy

               (

                _Msg_Content_Bytes

                , 0

                , bytes

                , i, _Msg_Content_Bytes.Length

               );

            //LinkID

            i += (int)_Msg_Length;

            buffer = Encoding.ASCII.GetBytes(_LinkID);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //20

            return bytes;

        }

        public ulong Msg_Id

        {

            get

            {

                return _Msg_Id;

            }

            set

            {

                _Msg_Id = value;

            }

        }

        public uint Pk_total

        {

            get

            {

                return _Pk_total;

            }

            set

            {

                _Pk_total = value;

            }

        }

        public uint Pk_number

        {

            get

            {

                return _Pk_number;

            }

            set

            {

                _Pk_number = value;

            }

        }

        public uint Registered_Delivery

        {

            get

            {

                return _Registered_Delivery;

            }

            set

            {

                _Registered_Delivery = value;

            }

        }

        public uint Msg_level

        {

            get

            {

                return _Msg_level;

            }

            set

            {

                _Msg_level = value;

            }

        }

        public string Service_Id

        {

            get

            {

                return _Service_Id;

            }

            set

            {

                _Service_Id = value;

            }

        }

        public uint Fee_UserType

        {

            get

            {

                return _Fee_UserType;

            }

            set

            {

                _Fee_UserType = value;

            }

        }

        public string Fee_terminal_Id

        {

            get

            {

                return _Fee_terminal_Id;

            }

            set

            {

                _Fee_terminal_Id = value;

            }

        }

        public uint Fee_terminal_type

        {

            get

            {

                return _Fee_terminal_type;

            }

            set

            {

                _Fee_terminal_type = value;

            }

        }

        public uint TP_pId

        {

            get

            {

                return _TP_pId;

            }

            set

            {

                _TP_pId = value;

            }

        }

        public uint TP_udhi

        {

            get

            {

                return _TP_udhi;

            }

            set

            {

                _TP_udhi = value;

            }

        }

        public uint Msg_Fmt

        {

            get

            {

                return _Msg_Fmt;

            }

            set

            {

                _Msg_Fmt = value;

                if (_Msg_Content != null)

                {

                    SetHeader();

                }

            }

        }

        public string Msg_src

        {

            get

            {

                return _Msg_src;

            }

            set

            {

                _Msg_src = value;

            }

        }

        public string FeeType

        {

            get

            {

                return _FeeType;

            }

            set

            {

                _FeeType = value;

            }

        }

        public string FeeCode

        {

            get

            {

                return _FeeCode;

            }

            set

            {

                _FeeCode = value;

            }

        }

        public string ValId_Time

        {

            get

            {

                return _ValId_Time;

            }

            set

            {

                _ValId_Time = value;

            }

        }

        public string At_Time

        {

            get

            {

                return _At_Time;

            }

            set

            {

                _At_Time = value;

            }

        }

        public string Src_Id

        {

            get

            {

                return _Src_Id;

            }

            set

            {

                _Src_Id = value;

            }

        }

        public uint DestUsr_tl

        {

            get

            {

                return _DestUsr_tl;

            }

            set

            {

                _DestUsr_tl = value;

            }

        }

        public string[] Dest_terminal_Id

        {

            get

            {

                return _Dest_terminal_Id;

            }

            set

            {

                _Dest_terminal_Id = value;

            }

        }

        public uint Dest_terminal_type

        {

            get

            {

                return _Dest_terminal_type;

            }

            set

            {

                _Dest_terminal_type = value;

            }

        }

        public uint Msg_Length

        {

            get

            {

                return _Msg_Length;

            }

            set

            {

                _Msg_Length = value;

            }

        }

        public string Msg_Content

        {

            get

            {

                return _Msg_Content;

            }

            set

            {

                _Msg_Content = value;

                SetHeader();

            }

        }

        public string LinkId

        {

            get

            {

                return _LinkID;

            }

            set

            {

                _LinkID = value;

            }

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

              (

               "MessageBody:"

               + "{0}At_Time: {1}"

               + "{0}BodyLength: {2}"

               + "{0}Dest_terminal_Id: {3}"

               + "{0}Dest_terminal_type: {4}"

               + "{0}DestUsr_tl: {5}"

               + "{0}Fee_terminal_Id: {6}"

               + "{0}Fee_terminal_type: {7}"

               + "{0}Fee_UserType: {8}"

               + "{0}FeeCode: {9}"

               + "{0}FeeType: {10}"

               + "{0}LinkID: {11}"

               + "{0}Msg_Content: {12}"

               + "{0}Msg_Fmt: {13}"

               + "{0}Msg_Id: {14}"

               + "{0}Msg_Length: {15}"

               + "{0}Msg_level: {16}"

               + "{0}Msg_src: {17}"

               + "{0}Pk_number: {18}"

               + "{0}Pk_total: {19}"

               + "{0}Registered_Delivery: {20}"

               + "{0}Sequence_Id: {21}"

               + "{0}Service_Id: {22}"

               + "{0}Src_Id: {23}"

               + "{0}TP_pId: {24}"

               + "{0}TP_udhi: {25}"

               + "{0}ValId_Time: {26}"

               , "\r\n\t\t"

               , _At_Time

               , _BodyLength

               , String.Join(",", _Dest_terminal_Id)

               , _Dest_terminal_type

               , _DestUsr_tl

               , _Fee_terminal_Id

               , _Fee_terminal_type

               , _Fee_UserType

               , _FeeCode

               , _FeeType

               , _LinkID

               , _Msg_Content

               , _Msg_Fmt

               , _Msg_Id

               , _Msg_Length

               , _Msg_level

               , _Msg_src

               , _Pk_number

               , _Pk_total

               , _Registered_Delivery

               , _Sequence_Id

               , _Service_Id

               , _Src_Id

               , _TP_pId

               , _TP_udhi

               , _ValId_Time

              )

              + "\r\n]";

        }

    }

    public class CMPP_SUBMIT_RESP //: CMPP_Response

    {

        private MessageHeader _Header;

        private uint _Msg_Id;

        private uint _Result;

        public const int BodyLength = 8 + 4;

        public uint Msg_Id

        {

            get

            {

                return _Msg_Id;

            }

        }

        public uint Result

        {

            get

            {

                return _Result;

            }

        }

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public CMPP_SUBMIT_RESP(byte[] bytes)

        {

            int i = 0;

            byte[] buffer = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

            _Header = new MessageHeader(buffer);

            //Msg_Id

            i += MessageHeader.Length;

            buffer = new byte[8];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Msg_Id = BitConverter.ToUInt32(buffer, 0);

            //Result

            i += 8;

            buffer = new byte[4];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Result = BitConverter.ToUInt32(buffer, 0);

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

               (

                "MessageBody:"

                + "{0}Msg_Id: {1}"

                + "{0}Result: {2}"

                , "\r\n\t\t"

                , _Msg_Id

                , _Result

               )

              + "\r\n]";

        }

    }

    public class CMPP_DELIVER //: CMPP_Request

    {

        public ulong Msg_Id

        {

            get

            {

                return _Msg_Id;

            }

        }

        public string Dest_Id

        {

            get

            {

                return _Dest_Id;

            }

        }

        public string Service_Id

        {

            get

            {

                return _Service_Id;

            }

        }

        public uint TP_pid

        {

            get

            {

                return _TP_pid;

            }

        }

        public uint TP_udhi

        {

            get

            {

                return _TP_udhi;

            }

        }

        public uint Msg_Fmt

        {

            get

            {

                return _Msg_Fmt;

            }

        }

        public string Src_terminal_Id

        {

            get

            {

                return _Src_terminal_Id;

            }

        }

        public uint Src_terminal_type

        {

            get

            {

                return _Src_terminal_type;

            }

        }

        public uint Registered_Delivery

        {

            get

            {

                return _Registered_Delivery;

            }

        }

        public uint Msg_Length

        {

            get

            {

                return _Msg_Length;

            }

        }

        public string Msg_Content

        {

            get

            {

                return _Msg_Content;

            }

        }

        public string LinkId

        {

            get

            {

                return _LinkID;

            }

        }

        private ulong _Msg_Id; // 8 Unsigned Integer 信息标识。

        // 生成算法如下:

        // 采用64位(8字节)的整数:

        // (1)????????? 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中

        // bit64~bit61:月份的二进制表示;

        // bit60~bit56:日的二进制表示;

        // bit55~bit51:小时的二进制表示;

        // bit50~bit45:分的二进制表示;

        // bit44~bit39:秒的二进制表示;

        // (2)????????? 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中;

        // (3)????????? 序列号:bit16~bit1,顺序增加,步长为1,循环使用。

        // 各部分如不能填满,左补零,右对齐。

        private string _Dest_Id; // 21 Octet String 目的号码。

        // SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。

        private string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

        private uint _TP_pid; // 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9。

        private uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

        private uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

        // 0:ASCII串;

        // 3:短信写卡操作;

        // 4:二进制信息;

        // 8:UCS2编码;

        // 15:含GB汉字。

        private string _Src_terminal_Id; // 32 Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)。

        private uint _Src_terminal_type; // 1 Unsigned Integer 源终端号码类型,0:真实号码;1:伪码。

        private uint _Registered_Delivery; // 1 Unsigned Integer 是否为状态报告:

        // 0:非状态报告;

        // 1:状态报告。

        private uint _Msg_Length; // 1 Unsigned Integer 消息长度,取值大于或等于0。

        private string _Msg_Content; // Msg_length Octet String 消息内容。

        private string _LinkID; // 20 Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

        private MessageHeader _Header;

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public const int FixedBodyLength = 8 // Msg_Id Unsigned Integer 信息标识。

            // 生成算法如下:

            // 采用64位(8字节)的整数:

            // (1)????????? 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中

            // bit64~bit61:月份的二进制表示;

            // bit60~bit56:日的二进制表示;

            // bit55~bit51:小时的二进制表示;

            // bit50~bit45:分的二进制表示;

            // bit44~bit39:秒的二进制表示;

            // (2)????????? 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中;

            // (3)????????? 序列号:bit16~bit1,顺序增加,步长为1,循环使用。

            // 各部分如不能填满,左补零,右对齐。

                 + 21 // Dest_Id Octet String 目的号码。

            // SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。

                 + 10 // Service_Id Octet String 业务标识,是数字、字母和符号的组合。

                 + 1 // TP_pid Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9。

                 + 1 // TP_udhi Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

                 + 1 // Msg_Fmt Unsigned Integer 信息格式:

            // 0:ASCII串;

            // 3:短信写卡操作;

            // 4:二进制信息;

            // 8:UCS2编码;

            // 15:含GB汉字。

                 + 32 // Src_terminal_Id Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)。

                 + 1 // Src_terminal_type Unsigned Integer 源终端号码类型,0:真实号码;1:伪码。

                 + 1 // Registered_Delivery Unsigned Integer 是否为状态报告:

            // 0:非状态报告;

            // 1:状态报告。

                 + 1 // Msg_Length Unsigned Integer 消息长度,取值大于或等于0。

            //Msg_length // Msg_Content Octet String 消息内容。

                 + 20; // LinkID Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

        private int _BodyLength;

        public int BodyLength

        {

            get

            {

                return _BodyLength;

            }

        }

        public CMPP_DELIVER(byte[] bytes)

        {

            int i = 0;

            byte[] buffer = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, 0, buffer, 0, MessageHeader.Length);

            _Header = new MessageHeader(buffer);

            //Msg_Id 8

            i += MessageHeader.Length;

            buffer = new byte[8];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _Msg_Id = BitConverter.ToUInt64(buffer, 0);

            string s = null;

            //Dest_Id 21

            i += 8;

            buffer = new byte[21];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            s = Encoding.ASCII.GetString(buffer).Trim();

            s = s.Substring(0, s.IndexOf('\0'));

            _Dest_Id = s;

            //Service_Id 20

            i += 21;

            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'));

            _Service_Id = s;

            //TP_pid 1

            i += 10;

            _TP_pid = (uint)bytes[i++];

            _TP_udhi = (uint)bytes[i++];

            _Msg_Fmt = (uint)bytes[i++];

            //Src_terminal_Id 32

            buffer = new byte[32];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            s = Encoding.ASCII.GetString(buffer).Trim();

            s = s.Substring(0, s.IndexOf('\0'));

            _Src_terminal_Id = s;

            //Src_terminal_type 1

            i += 32;

            _Src_terminal_type = (uint)bytes[i++];

            _Registered_Delivery = (uint)bytes[i++];

            _Msg_Length = (uint)bytes[i++];

            //Msg_Content

            buffer = new byte[_Msg_Length];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            switch (_Msg_Fmt)

            {

                case 8:

                    _Msg_Content = Encoding.BigEndianUnicode.GetString(buffer).Trim();

                    break;

                case 15: //gb2312

                    _Msg_Content = Encoding.GetEncoding("gb2312").GetString(buffer).Trim();

                    break;

                case 0: //ascii

                case 3: //短信写卡操作

                case 4: //二进制信息

                default:

                    _Msg_Content = Encoding.ASCII.GetString(buffer).ToString();

                    break;

            }

            //Linkid 20

            i += (int)_Msg_Length;

            buffer = new byte[20];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            s = Encoding.ASCII.GetString(buffer).Trim();

            s = s.Substring(0, s.IndexOf('\0'));

            _LinkID = s;

        }

        public byte[] ToBytes()

        {

            //Msg_Length Msg_Content

            byte[] buf;

            switch (_Msg_Fmt)

            {

                case 8:

                    buf = Encoding.BigEndianUnicode.GetBytes(_Msg_Content);

                    break;

                case 15: //gb2312

                    buf = Encoding.GetEncoding("gb2312").GetBytes(_Msg_Content);

                    break;

                case 0: //ascii

                case 3: //短信写卡操作

                case 4: //二进制信息

                default:

                    buf = Encoding.ASCII.GetBytes(_Msg_Content);

                    break;

            }

            _Msg_Length = (uint)buf.Length;

            _BodyLength = FixedBodyLength + (int)_Msg_Length;

            byte[] bytes = new byte[MessageHeader.Length + _BodyLength];

            int i = 0;

            byte[] buffer = null;

            //header 12

            _Header = new MessageHeader

                 (

                  (uint)(MessageHeader.Length + _BodyLength)

                  , CMPP_Command_Id.CMPP_DELIVER

                  , 0

                 );

            //Msg_Id 8

            i += MessageHeader.Length;

            buffer = new Byte[8];

            buffer = BitConverter.GetBytes(_Msg_Id);

            Array.Reverse(buffer);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //Dest_Id 21

            i += 8;

            buffer = new byte[21];

            buffer = Encoding.ASCII.GetBytes(_Dest_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //Service_Id 10

            i += 21;

            buffer = new byte[10];

            buffer = Encoding.ASCII.GetBytes(_Service_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //TP_pid 1

            i += 10;

            bytes[i++] = (byte)_TP_pid;

            bytes[i++] = (byte)_TP_udhi;

            bytes[i++] = (byte)_Msg_Fmt;

            //Src_terminal_Id 32

            buffer = new byte[32];

            buffer = Encoding.ASCII.GetBytes(_Src_terminal_Id);

            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //Src_terminal_type 1

            i += 32;

            bytes[i++] = (byte)_Src_terminal_type;

            bytes[i++] = (byte)_Registered_Delivery;

            bytes[i++] = (byte)_Msg_Length;

            //Msg_Content

            Buffer.BlockCopy(buf, 0, bytes, i, buf.Length);

            //LinkID

            i += (int)_Msg_Length;

            return bytes;

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

                 (

                  "MessageBody:"

                  + "{0}BodyLength: {1}"

                  + "{0}Dest_Id: {2}"

                  + "{0}LinkID: {3}"

                  + "{0}Msg_Content: {4}"

                  + "{0}Msg_Fmt: {5}"

                  + "{0}Msg_Id: {6}"

                  + "{0}Msg_Length: {7}"

                  + "{0}Registered_Delivery: {8}"

                  + "{0}Service_Id: {9}"

                  + "{0}Src_terminal_Id: {10}"

                  + "{0}Src_terminal_type: {11}"

                  + "{0}TP_pid: {12}"

                  + "{0}TP_udhi: {13}"

                  , "\r\n\t\t"

                  , _BodyLength

                  , _Dest_Id

                  , _LinkID

                  , _Msg_Content

                  , _Msg_Fmt

                  , _Msg_Id

                  , _Msg_Length

                  , _Registered_Delivery

                  , _Service_Id

                  , _Src_terminal_Id

                  , _Src_terminal_type

                  , _TP_pid

                  , _TP_udhi

                 )

              + "\r\n]";

        }

    }

    public class CMPP_DELIVER_RESP //: CMPP_Response

    {

        private MessageHeader _Header;

        private ulong _Msg_Id;

        private uint _Result;

        public const int Bodylength = 8 + 4;

        public CMPP_DELIVER_RESP(ulong Msg_Id, uint Result)

        {

            _Msg_Id = Msg_Id;

            _Result = Result;

        }

        public byte[] ToBytes()

        {

            int i = 0;

            byte[] bytes = new byte[MessageHeader.Length + Bodylength];

            byte[] buffer = new byte[MessageHeader.Length];

            //header

            _Header = new MessageHeader

                 (

                  MessageHeader.Length + Bodylength

                  , CMPP_Command_Id.CMPP_DELIVER_RESP

                  , 0

                 );

            buffer = _Header.ToBytes();

            Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

            i += MessageHeader.Length;

            //msg_id 8

            buffer = BitConverter.GetBytes(_Msg_Id);

            Array.Reverse(buffer);

            buffer.CopyTo(bytes, i);

            //result 4

            i += 8;

            buffer = BitConverter.GetBytes(_Result);

            Array.Reverse(buffer);

            buffer.CopyTo(bytes, i);

            return bytes;

        }

        public override string ToString()

        {

            return _Header.ToString() + "\r\n"

              + string.Format

                 (

                  "[\r\nMessageBody:"

                  + "\r\n\tMsg_Id: {0}"

                  + "\r\n\tResult: {1}"

                  + "\r\n]"

                  , _Msg_Id

                  , _Result

                 );

        }

    }

    public class CMPP_Msg_Content //状态报告

    {

        public const int BodyLength = 8

                + 7

                + 10

                + 10

                + 32

                + 4;

        private uint _Msg_Id; // 8 Unsigned Integer 信息标识。SP提交短信(CMPP_SUBMIT)操作时,与SP相连的ISMG产生的Msg_Id。

        private string _Stat; // 7 Octet String 发送短信的应答结果,含义详见表一。SP根据该字段确定CMPP_SUBMIT消息的处理状态。

        private string _Submit_time; // 10 Octet String YYMMDDHHMM(YY为年的后两位00-99,MM:01-12,DD:01-31,HH:00-23,MM:00-59)。

        private string _Done_time; // 10 Octet String YYMMDDHHMM。

        public CMPP_Msg_Content(byte[] bytes)

        {

            if (bytes.Length == BodyLength)

            {

                int i = 0;

                //_Msg_Id 8

                byte[] buffer = new byte[8];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                Array.Reverse(buffer);

                _Msg_Id = BitConverter.ToUInt32(buffer, 0);

                //_Stat 7

                i += 8;

                buffer = new byte[7];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                _Stat = Encoding.ASCII.GetString(buffer);

                //_Submit_time 10

                i += 7;

                buffer = new byte[10];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                _Submit_time = Encoding.ASCII.GetString(buffer);

                //_Done_time 10

                i += 10;

                buffer = new byte[10];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                _Submit_time = Encoding.ASCII.GetString(buffer);

                //Dest_terminal_Id 32

                i += 10;

                buffer = new byte[32];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                _Dest_terminal_Id = Encoding.ASCII.GetString(buffer);

                //SMSC_sequence 4

                i += 32;

                buffer = new byte[4];

                Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

                Array.Reverse(buffer);

                _SMSC_sequence = BitConverter.ToUInt32(buffer, 0);

            }

        }

        public uint Msg_Id

        {

            get

            {

                return _Msg_Id;

            }

            set

            {

                _Msg_Id = value;

            }

        }

        public string Stat

        {

            get

            {

                return _Stat;

            }

            set

            {

                _Stat = value;

            }

        }

        public string Submit_time

        {

            get

            {

                return _Submit_time;

            }

            set

            {

                _Submit_time = value;

            }

        }

        public string Done_time

        {

            get

            {

                return _Done_time;

            }

            set

            {

                _Done_time = value;

            }

        }

        public string Dest_terminal_Id

        {

            get

            {

                return _Dest_terminal_Id;

            }

            set

            {

                _Dest_terminal_Id = value;

            }

        }

        public uint SMSC_sequence

        {

            get

            {

                return _SMSC_sequence;

            }

            set

            {

                _SMSC_sequence = value;

            }

        }

        private string _Dest_terminal_Id; // 32 Octet String 目的终端MSISDN号码(SP发送CMPP_SUBMIT消息的目标终端)。

        private uint _SMSC_sequence; // 4 Unsigned Integer 取自SMSC发送状态报告的消息体中的消息标识。

        public override string ToString()

        {

            return string.Format

                (

                 "[\r\nMessageBody:"

                 + "\r\n\tBodyLength: {0}"

                 + "\r\n\tDest_terminal_Id: {1}"

                 + "\r\n\tDone_time: {2}"

                 + "\r\n\tMsg_Id: {3}"

                 + "\r\n\tSMSC_sequence: {4}"

                 + "\r\n\tStat: {5}"

                 + "\r\n\tSubmit_time: {6}"

                 + "\r\n]"

                 , CMPP_Msg_Content.BodyLength

                 , _Dest_terminal_Id

                 , _Done_time

                 , _Msg_Id

                 , _SMSC_sequence

                 , _Stat

                 , _Submit_time

                );

        }

    }

    public class CMPP_QUERY //: CMPP_Request

    {

        private MessageHeader _Header;

        private string _Time; // 8 Octet String 时间YYYYMMDD(精确至日)。

        private uint _Query_Type; // 1 Unsigned Integer 查询类别:

        // 0:总数查询;

        // 1:按业务类型查询。

        private string _Query_Code; // 10 Octet String 查询码。

        // 当Query_Type为0时,此项无效;当Query_Type为1时,此项填写业务类型Service_Id.。

        private string _Reserve; // 8 Octet String 保留。

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public string Time

        {

            get

            {

                return _Time;

            }

        }

        public uint Query_Type

        {

            get

            {

                return _Query_Type;

            }

        }

        public string Query_Code

        {

            get

            {

                return _Query_Code;

            }

        }

        public string Reserve

        {

            get

            {

                return _Reserve;

            }

        }

        public const int BodyLength = 8 + 1 + 10 + 8;

        public CMPP_QUERY

         (

           DateTime Time

           , uint Query_Type

           , string Query_Code

           , string Reserve

           , uint Sequence_Id

         )

        {

            _Time = Utility.Get_YYYYMMDD_String(Time);

            _Query_Type = Query_Type;

            _Query_Code = Query_Code;

            _Reserve = Reserve;

            _Header = new MessageHeader

                 (

                  (uint)(MessageHeader.Length + BodyLength)

                  , CMPP_Command_Id.CMPP_QUERY

                  , Sequence_Id

                 );

        }

        public byte[] ToBytes()

        {

            int i = 0;

            byte[] bytes = new byte[MessageHeader.Length + BodyLength];

            //header

            byte[] buffer = new byte[MessageHeader.Length];

            buffer = _Header.ToBytes();

            buffer.CopyTo(bytes, 0);

            //Time 8

            i += MessageHeader.Length;

            buffer = new byte[10];

            buffer = Encoding.ASCII.GetBytes(_Time);

            buffer.CopyTo(bytes, i);

            //Query_Type 1

            i += 8;

            bytes[i++] = (byte)_Query_Type;

            //Query_Code 10

            buffer = new byte[10];

            buffer = Encoding.ASCII.GetBytes(_Query_Code);

            buffer.CopyTo(bytes, i);

            //Reserve 8

            i += 10;

            buffer = new byte[8];

            buffer = Encoding.ASCII.GetBytes(_Reserve);

            buffer.CopyTo(bytes, i);

            return bytes;

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

                 (

                  "MessageBody:"

                  + "{0}Query_Code: {1}"

                  + "{0}Query_Type: {2}"

                  + "{0}Reserve: {3}"

                  + "{0}Time: {4}"

                  , "\r\n\t\t"

                  , _Query_Code

                  , _Query_Type

                  , _Reserve

                  , _Time

                 )

              + "\r\n]";

        }

    }

    public class CMPP_QUERY_RESP

    {

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public string Time

        {

            get

            {

                return _Time;

            }

        }

        public uint Query_Type

        {

            get

            {

                return _Query_Type;

            }

        }

        public string Query_Code

        {

            get

            {

                return _Query_Code;

            }

        }

        public uint Mt_TlMsg

        {

            get

            {

                return _MT_TLMsg;

            }

        }

        public uint Mt_Tlusr

        {

            get

            {

                return _MT_Tlusr;

            }

        }

        public uint Mt_Scs

        {

            get

            {

                return _MT_Scs;

            }

        }

        public uint MT_WT

        {

            get

            {

                return _MT_WT;

            }

        }

        public uint MT_FL

        {

            get

            {

                return _MT_FL;

            }

        }

        public uint MO_Scs

        {

            get

            {

                return _MO_Scs;

            }

        }

        public uint MO_WT

        {

            get

            {

                return _MO_WT;

            }

        }

        public uint MO_FL

        {

            get

            {

                return _MO_FL;

            }

        }

        private MessageHeader _Header;

        private string _Time; // 8 Octet String 时间(精确至日)。

        private uint _Query_Type; // 1 Unsigned Integer 查询类别:

        // 0:总数查询;

        // 1:按业务类型查询。

        private string _Query_Code; // 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 CMPP_QUERY_RESP(byte[] bytes)

        {

            int i = 0;

            //header 12

            byte[] buffer = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

            _Header = new MessageHeader(buffer);

            //Time 8

            i += MessageHeader.Length;

            buffer = new byte[8];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            _Time = Encoding.ASCII.GetString(buffer);

            //Query_Type 1

            i += 8;

            _Query_Type = (uint)bytes[i++];

            //Query_Code 10

            buffer = new byte[10];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            _Query_Code = Encoding.ASCII.GetString(buffer);

            //MT_TLMsg 4

            i += 10;

            buffer = new byte[4];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            Array.Reverse(buffer);

            _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);

            _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);

            _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);

            _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);

            _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);

            _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);

            _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);

            _MO_FL = BitConverter.ToUInt32(buffer, 0);

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "\t"

              + string.Format

                 (

                  "MessageBody:"

                  + "{0}BodyLength: {1}"

                  + "{0}MO_FL: {2}"

                  + "{0}MO_Scs: {3}"

                  + "{0}MO_WT: {4}"

                  + "{0}MT_FL: {5}"

                  + "{0}MT_Scs: {6}"

                  + "{0}MT_TLMsg: {7}"

                  + "{0}MT_Tlusr: {8}"

                  + "{0}MT_WT: {9}"

                  + "{0}Query_Code: {10}"

                  + "{0}Query_Type: {11}"

                  + "{0}Time: {12}"

                  , "\r\n\t\t"

                  , CMPP_QUERY_RESP.BodyLength

                  , _MO_FL

                  , _MO_Scs

                  , _MO_WT

                  , _MT_FL

                  , _MT_Scs

                  , _MT_TLMsg

                  , _MT_Tlusr

                  , _MT_WT

                  , _Query_Code

                  , _Query_Type

                  , _Time

                 )

              + "\r\n]";

        }

    }

    public class CMPP_ACTIVE_TEST

    {

        private MessageHeader _Header;

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public CMPP_ACTIVE_TEST(uint Sequence_Id)

        {

            _Header = new MessageHeader

                 (

                  MessageHeader.Length

                  , CMPP_Command_Id.CMPP_ACTIVE_TEST

                  , Sequence_Id

                 );

        }

        public byte[] ToBytes()

        {

            return _Header.ToBytes();

        }

        public override string ToString()

        {

            return _Header.ToString();

        }

    }

    public class CMPP_ACTIVE_TEST_RESP

    {

        private MessageHeader _Header;

        private byte _Reserved;

        public byte Reserved

        {

            get

            {

                return _Reserved;

            }

        }

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public CMPP_ACTIVE_TEST_RESP(byte[] bytes)

        {

            int i = 0;

            //header

            byte[] buffer = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

            _Header = new MessageHeader(buffer);

            //Reserved 1

            i += MessageHeader.Length;

            _Reserved = bytes[i];

        }

        public byte[] ToBytes()

        {

            return _Header.ToBytes();

        }

        public override string ToString()

        {

            return "[\r\n"

              + _Header.ToString() + "\r\n"

              + "]";

        }

    }

}

//CMPP Client

namespace Microshaoft.CMPP

{

    using System;

    using System.Net.Sockets;

    using System.Threading;

    using Microshaoft.CMPP.Messages;

    public class MessageEventArgs : EventArgs

    {

        private byte[] _HeaderData;

        private MessageHeader _Header;

        private byte[] _BodyData;

        public byte[] MessageBodyData

        {

            get

            {

                return _BodyData;

            }

        }

        public MessageHeader Header

        {

            get

            {

                return _Header;

            }

        }

        public byte[] MessageHeaderData

        {

            get

            {

                return _HeaderData;

            }

        }

        public MessageEventArgs(byte[] bytes)

        {

            _HeaderData = new byte[MessageHeader.Length];

            Buffer.BlockCopy(bytes, 0, _HeaderData, 0, MessageHeader.Length);

            _Header = new MessageHeader(_HeaderData);

            _BodyData = new byte[_Header.Total_Length - MessageHeader.Length];

            Buffer.BlockCopy(bytes, MessageHeader.Length, _BodyData, 0, _BodyData.Length);

        }

    }

    public class Client

    {

        private string _Host;

        private int _Port;

        private string _Source_Addr;

        private string _Password;

        private TcpClient tc;

        private bool _IsConnected;

        public bool IsConnected

        {

            get

            {

                return _IsConnected;

            }

        }

        private NetworkStream _NetworkStream;

        private static object _SyncLockObject = new object();

        public delegate void MessageEventHandler(Client Sender, MessageEventArgs e);

        //public delegate void RequestEventHandler(Client Sender, ResponseEventArgs e);

        public event MessageEventHandler ResponseMessageReceive;

        public event MessageEventHandler BeforeRequestMessageSend;

        public event MessageEventHandler AfterRequestMessageSended;

        private Thread _ReadResponseThread;

        private void OnBeforeRequestMessageSend(byte[] data)

        {

            if (BeforeRequestMessageSend != null)

            {

                BeforeRequestMessageSend(this, new MessageEventArgs(data));

            }

        }

        private void OnAfterRequestMessageSended(byte[] data)

        {

            if (AfterRequestMessageSended != null)

            {

                AfterRequestMessageSended(this, new MessageEventArgs(data));

            }

        }

        private void WriteToStreamWithLock(byte[] data, NetworkStream Stream)

        {

            OnBeforeRequestMessageSend(data);

            lock (_SyncLockObject)

            {

                Utility.WriteToStream(data, Stream);

            }

            OnAfterRequestMessageSended(data);

        }

        private byte[] ReadStreamToBytesWithLock(int Length, NetworkStream Stream)

        {

            lock (_SyncLockObject)

            {

                return Utility.ReadStreamToBytes(Length, Stream);

            }

        }

        public void Terminate(uint SequenceId)

        {

            MessageHeader terminate = new MessageHeader

                     (

                      MessageHeader.Length

                      , CMPP_Command_Id.CMPP_TERMINATE

                      , SequenceId

                     );

            Console.WriteLine("Request:\r\n{0}", terminate.ToString());

            WriteToStreamWithLock(terminate.ToBytes(), _NetworkStream);

            StartRun();

        }

        public void ActiveTest(uint SequenceId)

        {

            MessageHeader activeTest = new MessageHeader

                     (

                      MessageHeader.Length

                      , CMPP_Command_Id.CMPP_ACTIVE_TEST

                      , SequenceId

                     );

            //byte[] activeTest = activeTest.ToBytes();

            Console.WriteLine("Request:\r\n{0}", activeTest.ToString());

            WriteToStreamWithLock(activeTest.ToBytes(), _NetworkStream);

            StartRun();

        }

        public bool Connect

            (

             string Host

             , int Port

             , string UserID

             , string Password

             , uint SequenceId

            )

        {

            _Host = Host;

            _Port = Port;

            _Source_Addr = UserID;

            _Password = Password;

            DateTime ts = DateTime.Now;

            CMPP_CONNECT connect = new CMPP_CONNECT

                    (

                     _Source_Addr

                     , _Password

                     , ts

                     , 1

                     , SequenceId

                    );

            Console.WriteLine("Request:\r\n{0}", connect.ToString());

            tc = new TcpClient();

            tc.Connect(_Host, _Port);

            _NetworkStream = tc.GetStream();

            WriteToStreamWithLock(connect.ToBytes(), _NetworkStream);

            Run(ref _IsConnected);

            return _IsConnected;

        }

        public void Query

            (

             DateTime Time

             , uint QueryType

             , string QueryCode

             , string Reserve

             , uint SequenceId

            )

        {

            CMPP_QUERY query = new CMPP_QUERY

                   (

                    Time

                    , QueryType

                    , QueryCode

                    , Reserve

                    , SequenceId

                   );

            Console.WriteLine("Request:\r\n{0}", query.ToString());

            WriteToStreamWithLock(query.ToBytes(), _NetworkStream);

            StartRun();

        }

        public void Submit

            (

             ulong MsgId

             , uint RegisteredDelivery

             , string FeeTerminalId

             , string[] DestTerminalId

             , string MsgContent

             , uint SequenceId

            )

        {

            //这里的字段根据需要设定

            CMPP_SUBMIT submit = new CMPP_SUBMIT(SequenceId);

            submit.Msg_Id = MsgId; // uint _Msg_Id; // 8 Unsigned Integer 信息标识。

            submit.Pk_total = 1; // uint _Pk_total; // 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始。

            submit.Pk_number = 0; // uint _Pk_number; // 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始。

            submit.Registered_Delivery = RegisteredDelivery; // uint _Registered_Delivery; // 1 Unsigned Integer 是否要求返回状态确认报告:

            // // 0:不需要;

            // // 1:需要。

            submit.Msg_level = 1; // uint _Msg_level; // 1 Unsigned Integer 信息级别。

            submit.Service_Id = "abcdefghij"; // string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

            submit.Fee_UserType = 3; // uint _Fee_UserType; // 1 Unsigned Integer 计费用户类型字段:

            // // 0:对目的终端MSISDN计费;

            // // 1:对源终端MSISDN计费;

            // // 2:对SP计费;

            // // 3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。

            submit.Fee_terminal_Id = FeeTerminalId; // string _Fee_terminal_Id; // 32 Octet String 被计费用户的号码,当Fee_UserType为3时该值有效,当Fee_UserType为0、1、2时该值无意义。

            submit.Fee_terminal_type = 0; // uint _Fee_terminal_type; // 1 Unsigned Integer 被计费用户的号码类型,0:真实号码;1:伪码。

            submit.TP_pId = 0; // uint _TP_pId; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9。

            submit.TP_udhi = 0; // uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

            submit.Msg_Fmt = 15; // uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

            // // 0:ASCII串;

            // // 3:短信写卡操作;

            // // 4:二进制信息;

            // // 8:UCS2编码;

            // // 15:含GB汉字......

            submit.Msg_src = _Source_Addr; // string _Msg_src; // 6 Octet String 信息内容来源(SP_Id)。

            submit.FeeType = "02"; // string _FeeType; // 2 Octet String 资费类别:

            // // 01:对"计费用户号码"免费;

            // // 02:对"计费用户号码"按条计信息费;

            // // 03:对"计费用户号码"按包月收取信息费。

            submit.FeeCode = "100"; // string _FeeCode; // 6 Octet String 资费代码(以分为单位)。

            submit.ValId_Time = Utility.Get_MMDDHHMMSS_String(DateTime.Now.AddHours(2))

                 + "032+"; // string _ValId_Time; // 17 Octet String 存活有效期,格式遵循SMPP3.3协议。

            submit.At_Time = Utility.Get_MMDDHHMMSS_String(DateTime.Now) + "032+"; // string _At_Time; // 17 Octet String 定时发送时间,格式遵循SMPP3.3协议。

            //spnum

            submit.Src_Id = ""; // string _Src_Id; // 21 Octet String 源号码。SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,该号码最终在用户手机上显示为短消息的主叫号码。

            submit.Dest_terminal_Id = DestTerminalId; //new string[] {"1391xxx1138", "1391xxx1137"}; // string[] _Dest_terminal_Id; // 32*DestUsr_tl Octet String 接收短信的MSISDN号码。

            submit.DestUsr_tl = (uint)submit.Dest_terminal_Id.Length; // uint _DestUsr_tl; // 1 Unsigned Integer 接收信息的用户数量(小于100个用户)。

            submit.Dest_terminal_type = 0; // uint _Dest_terminal_type; // 1 Unsigned Integer 接收短信的用户的号码类型,0:真实号码;1:伪码。

            submit.Msg_Fmt = 15; // uint _Msg_Length; // 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节),取值大于或等于0。

            submit.Msg_Content = MsgContent; //"大家好!这是一个短信群发测试!"; // string _Msg_Content; // Msg_length Octet String 信息内容。

            submit.LinkId = ""; // string _LinkID; // 20 Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

            Console.WriteLine("Request:\r\n{0}", submit.ToString());

            WriteToStreamWithLock(submit.ToBytes(), _NetworkStream);

            StartRun();

        }

        bool _b = false;

        private bool _IsStarted = false;

        public void StartRun()

        {

            if (!_IsStarted)

            {

                _IsStarted = true;

                if (_ReadResponseThread == null)

                {

                    _ReadResponseThread = new Thread(new ThreadStart(Run));

                }

                if (_ReadResponseThread.ThreadState == ThreadState.Unstarted)

                {

                    _ReadResponseThread.Start();

                }

            }

        }

        private void Run()

        {

            Run(ref _b);

        }

        private void Run(ref bool BreakFlag)

        {

            while (!BreakFlag)

            {

                if (_NetworkStream.CanRead)

                {

                    if (_NetworkStream.DataAvailable)

                    {

                        byte[] buffer = new byte[MessageHeader.Length]; //Header

                        buffer = ReadStreamToBytesWithLock(MessageHeader.Length, _NetworkStream);

                        MessageHeader header = new MessageHeader(buffer);

                        byte[] bytes = new byte[header.Total_Length];

                        Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

                        int l = (int)header.Total_Length - MessageHeader.Length;

                        if (l > 0)

                        {

                            buffer = ReadStreamToBytesWithLock(l, _NetworkStream);

                            Buffer.BlockCopy

                               (

                                buffer

                                , 0

                                , bytes

                                , MessageHeader.Length

                                , buffer.Length

                               );

                        }

                        if (header.Command_Id == CMPP_Command_Id.CMPP_CONNECT_RESP)

                        {

                            CMPP_CONNECT_RESP connect_resp = new CMPP_CONNECT_RESP(bytes);

                            _IsConnected = connect_resp.Status == 0;

                        }

                        else if (header.Command_Id == CMPP_Command_Id.CMPP_TERMINATE_RESP)

                        {

                            _b = true;

                        }

                        if (ResponseMessageReceive != null)

                        {

                            ResponseMessageReceive(this, new MessageEventArgs(bytes));

                        }

                    }

                }

                Thread.Sleep(100);

            }

            if (_b)

            {

                _NetworkStream.Close();

                _NetworkStream.Dispose();

                _NetworkStream = null;

            }

        }

    }

}

//测试程序

namespace Test

{

    using System;

    using System.Text;

    using Microshaoft.CMPP;

    using Microshaoft.CMPP.Messages;

    class ConsoleApplication

    {

        static void Main()

        {

            ConsoleApplication a = new ConsoleApplication();

            Client c = new Client();

            c.ResponseMessageReceive += new Client.MessageEventHandler(a.c_ResponseMessageReceive);

            c.AfterRequestMessageSended += new Client.MessageEventHandler(a.c_AfterRequestMessageSended);

            Console.WriteLine("press 'q' to exit this programe!");

            uint i = 0; //Sequence_Id header

            ulong l = 0; //Msg_Id body

            if (c.Connect("localhost", 7891, "901234", "1234", ++i))

            {

                c.Submit

                 (

                   ++l

                   , 1

                   , "1391xxx1138"

                   , new string[] { "13911234567", "13911234567" }

                     , "卧鼠藏虫 身披七彩祥云 脚踏金甲圣衣"

                   , ++i

                 );

                c.Query(DateTime.Parse("2005-1-1"), 1, "001", "", ++i);

                c.Query(DateTime.Parse("2005-1-1"), 1, "001", "", ++i);

                c.ActiveTest(++i);

                c.Submit

                 (

                   ++l

                   , 1

                   , "1391xxx1138"

                   , new string[] { "13911234567" }

                     , "欲穷千里目 粒粒皆辛苦"

                   , ++i

                 );

            }

            string s;

            while ((s = Console.ReadLine()) != "q")

            {

                if (c.IsConnected)

                {

                    if (s.Length > 0)

                    {

                        c.Submit

                         (

                           ++l

                           , 1

                           , "1391xxx1138"

                           , new string[] { "13911234567", "13911234567" }

                           , s

                           , ++i

                         );

                        //Console.WriteLine("Request: Sequence_Id: {0},Msg_Id: {1}, Content: \"{2}\"", i, l, s);

                    }

                    else

                    {

                        Console.WriteLine("you can submit your SMS at here,or press 'q' to exit this programe!");

                    }

                }

            }

            if (c.IsConnected)

            {

                c.Terminate(++i);

            }

            Console.ReadLine();

        }

        private void c_ResponseMessageReceive(Client Sender, MessageEventArgs e)

        {

            MessageHeader header = e.Header;

            //PrintHeader(header);

            byte[] bytes = new byte[header.Total_Length];

            header.ToBytes().CopyTo(bytes, 0);

            e.MessageBodyData.CopyTo(bytes, MessageHeader.Length);

            string s = "";

            if (header.Command_Id == CMPP_Command_Id.CMPP_ACTIVE_TEST_RESP)

            {

                CMPP_ACTIVE_TEST_RESP response = new CMPP_ACTIVE_TEST_RESP(bytes);

                //Console.WriteLine(response.Reserved);

                s = response.ToString();

            }

            else if (header.Command_Id == CMPP_Command_Id.CMPP_CONNECT_RESP)

            {

                CMPP_CONNECT_RESP response = new CMPP_CONNECT_RESP(bytes);

                s = response.ToString();

            }

            else if (header.Command_Id == CMPP_Command_Id.CMPP_QUERY_RESP)

            {

                CMPP_QUERY_RESP response = new CMPP_QUERY_RESP(bytes);

                s = response.ToString();

            }

            else if (header.Command_Id == CMPP_Command_Id.CMPP_SUBMIT_RESP)

            {

                CMPP_SUBMIT_RESP response = new CMPP_SUBMIT_RESP(bytes);

                s = response.ToString();

            }

            else if (header.Command_Id == CMPP_Command_Id.CMPP_TERMINATE_RESP)

            {

                s = String.Format("good bye");

            }

            //上行短信

            else if (header.Command_Id == CMPP_Command_Id.CMPP_DELIVER)

            {

                CMPP_DELIVER response = new CMPP_DELIVER(bytes);

                if (response.Registered_Delivery == 0) //普通短信

                {

                    s = String.Format("收到普通短信: \n{0}", response.ToString());

                }

                else

                //该模拟器不能自动生成状态报告再下发!请自行键入下面短信内容后,发送

                //状态报告短信: 00000001DELIVRD031213505003121350501391xxx11381391xxx11381391xx11380001

                {

                    CMPP_Msg_Content x = new CMPP_Msg_Content(Encoding.ASCII.GetBytes(response.Msg_Content));

                    s = x.ToString();

                }

            }

            Console.WriteLine("Response Received:\r\n" + s + "\n");

        }

        public void PrintHeader(MessageHeader Header)

        {

            Console.WriteLine("Response: Sequence_Id: {0}!", Header.Sequence_Id);

            Console.WriteLine("Total_Length: {0}!", Header.Total_Length);

            Console.WriteLine("Command_Id: {0}!", Header.Command_Id);

        }

        private void c_AfterRequestMessageSended(Client Sender, MessageEventArgs e)

        {

            Console.WriteLine("Sended {0} Request!", e.Header.Command_Id);

            //Console.ReadLine();

        }

    }

}



你可能感兴趣的:(client)