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;
            }
        }
    }
    
    
  • 相关阅读:
    Logistic Regression
    Bootstrap研究2布局系统杂记
    《Programming in Scala》读书笔记(持续更新) passover的个人空间 DOIT博客 多易网
    《Scala, Erlang, F#作者讨论函数式语言》有感
    用python抓取oj题目(0)——重回战场 duoduo3_69 博客园
    Netty vs Apache MINA
    What is Akka?
    Fault Tolerance (Scala) — Akka Documentation
    execute phase · mrdon/mavencliplugin Wiki
    netty和mina的比较
  • 原文地址:https://www.cnblogs.com/Microshaoft/p/1336678.html
Copyright © 2011-2022 走看看