zoukankan      html  css  js  c++  java
  • 中国移动短信网关通信 CMPP 3.0 ISMG SPClient Socket (Release 3)

    
    /*
    2008-11-20
    由于相关资源已经失效,现上传至本博客,请下载
    https://files.cnblogs.com/Microshaoft/CMPP3.ISMG.zip
    .Net/C# 实现 中国移动 CMPP v3.0 ISMG <-> SP 收发短信的 SP 客户端 (第3版)(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.
    */
    //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: [{3}]"
                            , "\r\n\t\t"
                            , _Command_Id
                            , _Sequence_Id
                            , _Total_Length
                        );
            }
        }
        public class CMPP_CONNECT                                    //: CMPP_Request
        {
            public const int _FixedBodyLength = 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
                (
                    uint Sequence_Id //header
                    , string Source_Addr
                    , string Password
                    , uint Version
                    , DateTime Timestamp
                )
            {
                _Header = new MessageHeader
                                (
                                    MessageHeader.Length + _FixedBodyLength
                                    , CMPP_Command_Id.CMPP_CONNECT
                                    , Sequence_Id
                                );
                _Source_Addr = Source_Addr;
                _Password = Password;
                string s = DateTimeHelper.Get_MMddHHmmss_String(Timestamp);
                _Timestamp = IntegerHelper.UInt32Parse(s);//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 = CryptoHelper.ComputeMD5(buffer);//new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);
                _Version = Version;
            }
            public byte[] ToBytes()
            {
                int i = 0;
                byte[] bytes = new byte[MessageHeader.Length + _FixedBodyLength];
                //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"
                                        , CryptoHelper.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"
                                , CryptoHelper.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('\0');
                //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('\0');
                //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('\0');
                //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('\0');
                        break;
                    case 15 : //gb2312
                        _Msg_Content = Encoding.GetEncoding("gb2312").GetString(buffer).Trim('\0');
                        break;
                    case 0 : //ascii
                    case 3 : //短信写卡操作
                    case 4 : //二进制信息
                    default :
                        _Msg_Content = Encoding.ASCII.GetString(buffer).Trim('\0');
                        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('\0');
                //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;
                _Header = new MessageHeader
                                    (
                                        MessageHeader.Length + Bodylength
                                        , CMPP_Command_Id.CMPP_DELIVER_RESP
                                        , 0
                                    );
            }
            public byte[] ToBytes()
            {
                int i = 0;
                byte[] bytes = new byte[MessageHeader.Length + Bodylength];
                byte[] buffer = new byte[MessageHeader.Length];
                //header
                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).Trim('\0');
                    //_Submit_time 10
                    i += 7;
                    buffer = new byte[10];
                    Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                    _Submit_time = Encoding.ASCII.GetString(buffer).Trim('\0');
                    //_Done_time 10
                    i += 10;
                    buffer = new byte[10];
                    Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
                    _Submit_time = Encoding.ASCII.GetString(buffer).Trim('\0');
                    //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).Trim('\0');
                    //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 = DateTimeHelper.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).Trim('\0');
                //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).Trim('\0');
                //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;
        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 MessageReceive;
            public event MessageEventHandler BeforeMessageSend;
            public event MessageEventHandler AfterMessageSended;
            private Thread _ReadResponseThread;
            private void OnBeforeMessageSend(byte[] data)
            {
                if (BeforeMessageSend != null)
                {
                    BeforeMessageSend(this, new MessageEventArgs(data));
                }
            }
            private void OnAfterMessageSended(byte[] data)
            {
                if (AfterMessageSended != null)
                {
                    AfterMessageSended(this, new MessageEventArgs(data));
                }
            }
            private void SendData(byte[] data)
            {
                OnBeforeMessageSend(data);
                lock (_SyncLockObject)
                {
                    _Socket.Send(data);
                }
                OnAfterMessageSended(data);
            }
            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());
                SendData(terminate.ToBytes());
                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());
                SendData(activeTest.ToBytes());
                //            StartRun();
            }
            public void DeliverResponse(ulong Msg_Id, uint Result)
            {
                CMPP_DELIVER_RESP response = new CMPP_DELIVER_RESP(Msg_Id, Result);
                byte[] data = response.ToBytes();
                //byte[] activeTest = activeTest.ToBytes();
                Console.WriteLine("Request:\r\n{0}", response.ToString());
                SendData(response.ToBytes());
            }
            public bool Connect
                            (
                                string Host
                                , int Port
                                , string UserID
                                , string Password
                                , uint SequenceId //header
                                , uint Version
                                , DateTime time
                            )
            {
                _Host = Host;
                _Port = Port;
                _Source_Addr = UserID;
                _Password = Password;
                CMPP_CONNECT connect = new CMPP_CONNECT
                                                (
                                                    SequenceId //header
                                                    , _Source_Addr
                                                    , _Password
                                                    , Version
                                                    , time
                                                );
                Console.WriteLine("Request:\r\n{0}", connect.ToString());
                if (_Socket == null)
                {
                    _Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }
                //tc = new TcpClient();
                _Socket.Connect(_Host, _Port); //连接
                //tc.Connect(_Host, _Port);
                //_NetworkStream = tc.GetStream();
                //WriteToStreamWithLock(connect.ToBytes(), _NetworkStream);
                //WriteToStreamWithLock(connect.ToBytes(), _NetworkStream);
                SendData(connect.ToBytes());
                //_Socket.Send(connect.ToBytes());
                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());
                SendData(query.ToBytes());
                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 = DateTimeHelper.Get_MMddHHmmss_String(DateTime.Now.AddHours(2))
                                    + "032+";                                                    //    string _ValId_Time;     // 17 Octet String 存活有效期,格式遵循SMPP3.3协议。
                submit.At_Time = DateTimeHelper.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());
                SendData(submit.ToBytes());
            }
            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 Socket _Socket;
            private void Run(ref bool BreakFlag)
            {
                while (!BreakFlag)
                {
                    //long L = _NetworkStream.Length;
                    byte[] buffer = SocketDataHelper.ReadDataToFixedLengthBytes(MessageHeader.Length, _Socket);
                    MessageHeader header = new MessageHeader(buffer);
                    int l = (int) header.Total_Length - MessageHeader.Length;
                    byte[] bytes = new byte[header.Total_Length]; //header + body
                    Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length); //header
                    if (l > 0)
                    {
                        buffer = SocketDataHelper.ReadDataToFixedLengthBytes(l, _Socket);
                        Buffer.BlockCopy(buffer, 0, bytes, MessageHeader.Length, buffer.Length); //header
                    }
                    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 (MessageReceive != null)
                    {
                        MessageReceive(this, new MessageEventArgs(bytes));
                    }
                    Thread.Sleep(100);
                }
            }
        }
    }
    //测试程序
    namespace Test
    {
        using System;
        using System.Text;
        using Microshaoft;
        using Microshaoft.CMPP;
        using Microshaoft.CMPP.Messages;
        class ConsoleApplication
        {
            static void Main()
            {
                ConsoleApplication a = new ConsoleApplication();
                Client c = new Client();
                c.MessageReceive += new Client.MessageEventHandler(a.c_MessageReceive);
                c.AfterMessageSended += new Client.MessageEventHandler(a.c_AfterMessageSended);
                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, 1, DateTime.Now))
                {
                    if (c.IsConnected)
                    {
                        c.StartRun();
                    }
                    c.Submit
                        (
                                ++l
                                , 1
                                , "1391xxx1138"
                                , new string[] { "13911234567" }
                                , "卧鼠藏虫 身披七彩祥云 脚踏金甲圣衣"
                                , ++i
                        );
                    c.Query(DateTimeHelper.Parse("2005-1-1"), 1, "001", "", ++i);
                    c.Query(DateTimeHelper.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)
                        {
                            if (s == "a")
                            {
                                c.ActiveTest(++i);
                            }
                            else
                            {
                                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_MessageReceive(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();
                    }
                    Sender.DeliverResponse(response.Msg_Id, 0);
                }
                ConsoleColor cc = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Response Received:\r\n" + s + "\n");
                Console.ForegroundColor = cc;
            }
            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_AfterMessageSended(Client Sender, MessageEventArgs e)
            {
                Console.WriteLine("Sended {0} Request!", e.Header.Command_Id);
                //Console.ReadLine();
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.IO;
        using System.Net.Sockets;
        public static class SocketDataHelper
        {
            public static void ReadDataToBytes
                                    (
                                        Socket socket,
                                        ref byte[] buffer
                                    )
            {
                int p = 0;
                int l = buffer.Length;
                while (p < l)
                {
                    int r = socket.Receive
                                        (
                                            buffer
                                            , p
                                            , l - p
                                            , SocketFlags.None
                                        );
                    p += r;
                }
            }
            public static byte[] ReadDataToFixedLengthBytes
                                        (
                                            int length ,
                                            Socket socket 
                                        )
            {
                int p = 0;
                byte[] data = new byte[length];
                while (p < length)
                {
                    int r = socket.Receive
                                        (
                                            data
                                            , p
                                            , length - p
                                            , SocketFlags.None
                                        );
                    p += r;
                }
                return data;
            }
        }
        public static class StreamDataHelper
        {
            private static byte[] ReadDataToBytes(Stream stream)
            {
                byte[] buffer = new byte[64 * 1024];
                MemoryStream ms = new MemoryStream();
                int r = 0;
                int l = 0;
                long position = -1;
                if (stream.CanSeek)
                {
                    position = stream.Position;
                    stream.Position = 0;
                }
                while (true)
                {
                    r = stream.Read(buffer, 0, buffer.Length);
                    if (r > 0)
                    {
                        l += r;
                        ms.Write(buffer, 0, r);
                    }
                    else
                    {
                        break;
                    }
                }
                byte[] bytes = new byte[l];
                ms.Position = 0;
                ms.Read(bytes, 0, (int) l);
                ms.Close();
                ms = null;
                if (position >= 0)
                {
                    stream.Position = position;
                }
                return bytes;
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Net.Sockets;
        using System.Globalization;
        public static class DateTimeHelper
        {
            public static string Get_MMddHHmmss_String(DateTime time)
            {
                return time.ToString("MMddHHmmss");
            }
            public static string Get_yyyyMMddHHmmss_String(DateTime time)
            {
                return time.ToString("yyyyMMddHHmmss");
            }
            public static string Get_yyyyMMdd_String(DateTime time)
            {
                return time.ToString("yyyyMMdd");
            }
            public static DateTime Parse_yyyyMMddHHmmss(string text)
            {
                DateTime time = DateTime.TryParseExact
                                    (
                                        text
                                        , "yyyyMMddHHmmss"
                                        , DateTimeFormatInfo.InvariantInfo
                                        , DateTimeStyles.None
                                        , out time
                                    ) ? time : DateTime.MinValue;
                return time;
            }
            public static DateTime Parse_MMddHHmmss(int year, string text)
            {
                return Parse_yyyyMMddHHmmss(year.ToString("0000") + text);
            }
            public static DateTime Parse(string text)
            {
                DateTime time = DateTime.TryParse
                        (
                            text
                            , out time
                        ) ? time : DateTime.MinValue;
                return time;
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Security.Cryptography;
        using System.Text;
        using System.IO;
        
        public class CryptoHelper
        {
            static public byte[] RSASignSHA1
                (
                    byte[] data
                    , string privateKey
                )
            {
                RSACryptoServiceProvider x = new RSACryptoServiceProvider();
                x.FromXmlString(privateKey);
                return x.SignHash
                            (
                                ComputeSHA1(data)
                                , "SHA1"
                            );
            }
            public static bool RSAVerifySHA1
                                    (
                                        byte[] data
                                        , string publicKey
                                        , byte[] signature
                                    )
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(publicKey);
                return provider.VerifyHash
                                    (
                                        ComputeSHA1(data)
                                        , "SHA1"
                                        , signature
                                    );
            }
            public static byte[] RSASignMD5
                (
                    byte[] data
                    , string privateKey
                )
            {
                RSACryptoServiceProvider x = new RSACryptoServiceProvider();
                x.FromXmlString(privateKey);
                return x.SignHash
                            (
                                ComputeMD5(data)
                                , "MD5"
                            );
            }
            public static bool RSAVerifyMD5
                                    (
                                        byte[] data
                                        , string publicKey
                                        , byte[] signature
                                    )
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(publicKey);
                return provider.VerifyHash
                                    (
                                        ComputeMD5(data)
                                        , "MD5"
                                        , signature
                                    );
            }
            public static byte[] RSAEncrypt
                                    (
                                        byte[] data
                                        , string publicKey
                                        , bool DoOAEPPadding
                                    )
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(publicKey);
                return provider.Encrypt(data, DoOAEPPadding);
            }
            public static byte[] RSADecrypt
                                    (
                                        byte[] data
                                        , string privateKey
                                        , bool DoOAEPPadding
                                    )
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(privateKey);
                return provider.Decrypt(data, DoOAEPPadding);
            }
            /// <summary>
            /// Crypto 的摘要说明。
            /// </summary>
            public static byte[] TripleDESDecrypt
                (
                    byte[] data
                    , byte[] Key
                    , byte[] IV
                )
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.Key = Key;
                des.IV = IV;
                return des.CreateDecryptor().TransformFinalBlock(data, 0, data.Length);
            }
            public static byte[] TripleDESDecrypt
                (
                    string text
                    , string Base64Key
                    , string Base64IV
                )
            {
                return TripleDESDecrypt
                    (
                        Convert.FromBase64String(text)
                        , Convert.FromBase64String(Base64Key)
                        , Convert.FromBase64String(Base64IV)
                    );
            }
            public static byte[] TripleDESDecrypt
                (
                    string text
                    , byte[] Key
                    , byte[] IV
                )
            {
                return TripleDESDecrypt
                    (
                        Convert.FromBase64String(text)
                        , Key
                        , IV
                    );
            }
            public static string TripleDESDecrypt
                (
                    string text
                    , string Base64Key
                    , string Base64IV
                    , Encoding e //原文的encoding
                )
            {
                return e.GetString
                    (
                        TripleDESDecrypt
                            (
                                text
                                , Base64Key
                                , Base64IV
                            )
                    );
            }
            public static string TripleDESDecrypt
                (
                    string text
                    , byte[] Key
                    , byte[] IV
                    , Encoding e //原文的encoding
                )
            {
                return e.GetString
                    (
                        TripleDESDecrypt
                            (
                                text
                                , Key
                                , IV
                            )
                    );
            }
            public static string GenerateTripleDESHexStringKey()
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.GenerateKey();
                return BytesArrayToHexString(des.Key);
            }
            public static string GenerateTripleDESHexStringIV()
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.GenerateIV();
                return BytesArrayToHexString(des.IV);
            }
            public static byte[] TripleDESEncrypt
                (
                    byte[] data
                    , byte[] Key
                    , byte[] IV
                )
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.Key = Key;
                des.IV = IV;
                return des.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
            }
            public static byte[] TripleDESEncrypt
                (
                    string text
                    , Encoding e
                    , byte[] Key
                    , byte[] IV
                )
            {
                return TripleDESEncrypt
                    (
                        e.GetBytes(text)
                        , Key
                        , IV
                    );
            }
            public static byte[] TripleDESEncrypt
                (
                    string text
                    , Encoding e
                    , string Base64Key
                    , string Base64IV
                )
            {
                return TripleDESEncrypt
                    (
                        text
                        , e
                        , Convert.FromBase64String(Base64Key)
                        , Convert.FromBase64String(Base64IV)
                    );
            }
            public static byte[] ComputeSHA1(byte[] data)
            {
                return new SHA1CryptoServiceProvider().ComputeHash(data);
            }
            public static byte[] ComputeSHA1(string text, Encoding e)
            {
                return ComputeSHA1(e.GetBytes(text));
            }
            public static byte[] ComputeSHA1(string text)
            {
                return ComputeSHA1(text, Encoding.UTF8);
            }
            public static byte[] ComputeSHA1(Stream stream)
            {
                return new SHA1CryptoServiceProvider().ComputeHash(stream);
            }
            public static byte[] ComputeMD5(byte[] data)
            {
                return new MD5CryptoServiceProvider().ComputeHash(data, 0, data.Length);
            }
            public static byte[] ComputeMD5(string text, Encoding e)
            {
                return ComputeMD5(e.GetBytes(text));
            }
            public static byte[] ComputeMD5(string text)
            {
                return ComputeMD5(text, Encoding.UTF8);
            }
            public static byte[] ComputeMD5(Stream stream)
            {
                return new MD5CryptoServiceProvider().ComputeHash(stream);
            }
            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;
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        public static class IntegerHelper
        {
            public static int Int32Parse(string text)
            {
                int i = int.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : int.MinValue;
                return i;
            }
            public static uint UInt32Parse(string text)
            {
                uint i = uint.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : uint.MaxValue;
                return i;
            }
            public static short Int16Parse(string text)
            {
                short i = short.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : short.MinValue;
                return i;
            }
            public static ushort UInt16Parse(string text)
            {
                ushort i = ushort.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : ushort.MaxValue;
                return i;
            }
            public static long Int64Parse(string text)
            {
                long i = long.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : long.MinValue;
                return i;
            }
            public static ulong UInt64Parse(string text)
            {
                ulong i = ulong.TryParse
                                (
                                    text
                                    , out i
                                ) ? i : ulong.MaxValue;
                return i;
            }
        }
    }
    
    
  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/Microshaoft/p/1336678.html
Copyright © 2011-2022 走看看