⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sms.cs

📁 这是2005年6月云南移动短信网关升级到3.0时写的
💻 CS
📖 第 1 页 / 共 5 页
字号:
//.Net/C# 实现 中国移动 CMPP v3.0 ISMG SP 收发短信的 SP 客户端 (第2版) (CMPP SP Client) 

/*
.Net/C# 实现 中国移动 CMPP v3.0 ISMG <-> SP 收发短信的 SP 客户端 (第2版)(CMPP SP Client)
增加了 CMPP Client 类
本程序严格按
《中国移动通信企业标准》之《中国移动通信互联网短信网关接口协议(China Mobile Point to Point)》(版本号: 3.0.0)
即: CMPP v3.0.0
http://www.spzone.net/protocol/CMPPV3.0.rar
文档,实现了下面消息的定义及其相关协议级交互:
8.4 业务提供商 (SP) 与互联网短信网关 (ISMG) 间的消息定义 8
8.4.1 SP 请求连接到 ISMG(CMPP_CONNECT) 操作 8
8.4.1.1 CMPP_CONNECT 消息定义 (SP -> ISMG) 8
8.4.1.2 CMPP_CONNECT_RESP消息定义 (ISMG -> SP) 9
8.4.2 SP 或 ISMG 请求拆除连接 (CMPP_TERMINATE)操作 9
8.4.2.1 CMPP_TERMINATE 消息定义 (SP -> ISMG 或 ISMG -> SP) 9
8.4.2.2 CMPP_TERMINATE_RESP 消息定义 (SP -> ISMG 或 ISMG -> SP) 10
8.4.3 SP 向 ISMG提交短信 (CMPP_SUBMIT) 操作 10
8.4.3.1 CMPP_SUBMIT 消息定义 (SP -> ISMG) 10
8.4.3.2 CMPP_SUBMIT_RESP 消息定义 (ISMG -> SP) 11
8.4.5 ISMG 向 SP 送交短信 (CMPP_DELIVER) 操作 13
8.4.5.1 CMPP_DELIVER 消息定义 (ISMG -> SP) 13
8.4.5.2 CMPP_DELIVER_RESP 消息定义 (SP -> ISMG) 16
8.4.7 链路检测 (CMPP_ACTIVE_TEST) 操作 17
8.4.7.1 CMPP_ACTIVE_TEST定义 (SP -> ISMG 或 ISMG <- SP) 17
8.4.7.2 CMPP_ACTIVE_TEST_RESP定义 (SP -> ISMG 或 ISMG <- SP) 17
可采用《中国移动通信 CMPP v3.0 短消息网关模拟器 v1.10》进行测试:
下载于: 《北京风起水流软件工作室》
http://www.zealware.com/download/cmpp3smg.rar
《中国移动通信 CMPP v3.0 短消息网关模拟器 v1.10》
http://tech.spforum.net/uploadfile/2006426181749702.rar
本程序以熟悉理解 CMPP 3.0 协议为主要目的,只将 "消息定义" 对象化,其相关协议级交互并未作更深层次的 OO!
也暂无任何错误处理程序!
消息定义的所有字段名称及其数据类型均与上述之 CMPP v3.0.0 文档完全一致!
其间参阅过 shanhe@CSDN or yexiong@cnBlogs 大作(在此鸣谢):
http://blog.csdn.net/shanhe/archive/2004/07/19/45383.aspx
http://cnblogs.com/yexiong/articles/115330.aspx
但其中有些消息定义字节错位,因此不能正常交互?!且对象化层次较高,不利于理解协议本身!
遂自己动手,丰衣足食,实现部分主要协议(SP 收发短信):
playyuer㊣Microshaoft.com Invent.
*/
namespace Microshaoft
{
    using System;
    using System.Net.Sockets;
    public class Utility
    {
        public static string BytesArrayToHexString(byte[] data)
        {
            return BitConverter.ToString(data).Replace("-", "");
        }
        public static byte[] HexStringToBytesArray(string text)
        {
            text = text.Replace(" ", "");
            int l = text.Length;
            byte[] buffer = new byte[l / 2];
            for (int i = 0; i < l; i += 2)
            {
                buffer[i / 2] = Convert.ToByte(text.Substring(i, 2), 16);
            }
            return buffer;
        }
        //private static object _SyncLockObject = new object();
        public static string Get_MMDDHHMMSS_String(DateTime dt)
        {
            return DateTime.Now.ToString("MMddhhmmss");
        }
        public static string Get_YYYYMMDD_String(DateTime dt)
        {
            return DateTime.Now.ToString("yyyyMMdd");
        }
        internal static void WriteToStream(byte[] bytes, NetworkStream Stream)
        {
            if (Stream.CanWrite)
            {
                //lock (_SyncLockObject)
                {
                    Stream.Write(bytes, 0, bytes.Length);
                }
            }
        }
        internal static byte[] ReadStreamToBytes(int Length, NetworkStream Stream)
        {
            byte[] bytes = null;
            if (Stream.CanRead)
            {
                if (Stream.DataAvailable)
                {
                    bytes = new byte[Length];
                    int l = 0;
                    //lock (_SyncLockObject)
                    {
                        while (l < Length)
                        {
                            int r;
                            r = Stream.Read(bytes, l, Length - l);
                            l += r;
                        }
                    }
                }
            }
            return bytes;
        }
    }
}
//CMPP 消息定义
namespace Microshaoft.CMPP.Messages
{
    using System;
    using System.Text;
    using System.Security.Cryptography;
    public enum CMPP_Command_Id : uint
    {
        CMPP_CONNECT = 0x00000001        //请求连接
        ,
        CMPP_CONNECT_RESP = 0x80000001      //请求连接应答
            ,
        CMPP_TERMINATE = 0x00000002       //终止连接
            ,
        CMPP_TERMINATE_RESP = 0x80000002      //终止连接应答
            ,
        CMPP_SUBMIT = 0x00000004        //提交短信
            ,
        CMPP_SUBMIT_RESP = 0x80000004       //提交短信应答
            ,
        CMPP_DELIVER = 0x00000005        //短信下发
            ,
        CMPP_DELIVER_RESP = 0x80000005      //下发短信应答
            ,
        CMPP_QUERY = 0x00000006        //发送短信状态查询
            ,
        CMPP_QUERY_RESP = 0x80000006       //发送短信状态查询应答
            ,
        CMPP_CANCEL = 0x00000007        //删除短信
            ,
        CMPP_CANCEL_RESP = 0x80000007       //删除短信应答
            ,
        CMPP_ACTIVE_TEST = 0x00000008       //激活测试
            ,
        CMPP_ACTIVE_TEST_RESP = 0x80000008     //激活测试应答
            ,
        CMPP_FWD = 0x00000009         //消息前转
            ,
        CMPP_FWD_RESP = 0x80000009       //消息前转应答
            ,
        CMPP_MT_ROUTE = 0x00000010       //MT路由请求
            ,
        CMPP_MT_ROUTE_RESP = 0x80000010      //MT路由请求应答
            ,
        CMPP_MO_ROUTE = 0x00000011       //MO路由请求
            ,
        CMPP_MO_ROUTE_RESP = 0x80000011      //MO路由请求应答
            ,
        CMPP_GET_MT_ROUTE = 0x00000012      //获取MT路由请求
            ,
        CMPP_GET_MT_ROUTE_RESP = 0x80000012     //获取MT路由请求应答
            ,
        CMPP_MT_ROUTE_UPDATE = 0x00000013      //MT路由更新
            ,
        CMPP_MT_ROUTE_UPDATE_RESP = 0x80000013    //MT路由更新应答
            ,
        CMPP_MO_ROUTE_UPDATE = 0x00000014      //MO路由更新
            ,
        CMPP_MO_ROUTE_UPDATE_RESP = 0x80000014    //MO路由更新应答
            ,
        CMPP_PUSH_MT_ROUTE_UPDATE = 0x00000015    //MT路由更新
            ,
        CMPP_PUSH_MT_ROUTE_UPDATE_RESP = 0x80000015   //MT路由更新应答
            ,
        CMPP_PUSH_MO_ROUTE_UPDATE = 0x00000016    //MO路由更新
            ,
        CMPP_PUSH_MO_ROUTE_UPDATE_RESP = 0x80000016   //MO路由更新应答
            ,
        CMPP_GET_MO_ROUTE = 0x00000017      //获取MO路由请求
            , CMPP_GET_MO_ROUTE_RESP = 0x80000017     //获取MO路由请求应答
    }
    public class MessageHeader //消息头
    {
        public const int Length = 4 + 4 + 4;
        public CMPP_Command_Id Command_Id
        {
            get
            {
                return _Command_Id;
            }
        }
        public uint Sequence_Id
        {
            get
            {
                return _Sequence_Id;
            }
        }
        public uint Total_Length
        {
            get
            {
                return _Total_Length;
            }
        }
        private uint _Total_Length;        // 4 Unsigned Integer 消息总长度(含消息头及消息体)
        private CMPP_Command_Id _Command_Id;     // 4 Unsigned Integer 命令或响应类型
        private uint _Sequence_Id;        // 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)
        public MessageHeader
          (
           uint Total_Length
           , CMPP_Command_Id Command_Id
           , uint Sequence_Id
          ) //发送前
        {
            _Total_Length = Total_Length;
            _Command_Id = Command_Id;
            _Sequence_Id = Sequence_Id;
        }
        public MessageHeader(byte[] bytes)
        {
            byte[] buffer = new byte[4];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            _Total_Length = BitConverter.ToUInt32(buffer, 0);
            Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            _Command_Id = (CMPP_Command_Id)BitConverter.ToUInt32(buffer, 0);
            Buffer.BlockCopy(bytes, 8, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            _Sequence_Id = BitConverter.ToUInt32(buffer, 0);
        }
        public byte[] ToBytes()
        {
            byte[] bytes = new byte[MessageHeader.Length];
            byte[] buffer = BitConverter.GetBytes(_Total_Length);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 0, 4);
            buffer = BitConverter.GetBytes((uint)_Command_Id);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 4, 4);
            buffer = BitConverter.GetBytes(_Sequence_Id);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, 8, 4);
            return bytes;
        }
        public override string ToString()
        {
            return string.Format
              (
               "\tMessageHeader:{0}Command_Id: {1}{0}Sequence_Id: {2}{0}Total_Length: {2}"
               , "\r\n\t\t"
               , _Command_Id
               , _Sequence_Id
               , _Total_Length
              );
        }
    }
    public class CMPP_CONNECT         //: CMPP_Request
    {
        public const int BodyLength = 6 + 16 + 1 + 4;
        private string _Source_Addr;       // 6 Octet String 源地址,此处为SP_Id,即SP的企业代码。
        private string _Password;
        private byte[] _AuthenticatorSource;     // 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:
        //   AuthenticatorSource =
        //   MD5(Source_Addr+9 字节的0 +shared secret+timestamp)
        //   Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。
        private uint _Version;         // 1 Unsigned Integer 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号),对于3.0的版本,高4bit为3,低4位为0
        private uint _Timestamp;        // 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。
        private MessageHeader _Header;
        public MessageHeader Header
        {
            get
            {
                return _Header;
            }
        }
        public byte[] AuthenticatorSource
        {
            get
            {
                return _AuthenticatorSource;
            }
        }
        public CMPP_CONNECT
         (
          string Source_Addr
          , string Password
          , DateTime Timestamp
          , uint Version
          , uint Sequence_Id
         )
        {
            _Header = new MessageHeader
                (
                 MessageHeader.Length + BodyLength
                 , CMPP_Command_Id.CMPP_CONNECT
                 , Sequence_Id
                );
            _Source_Addr = Source_Addr;
            _Password = Password;
            string s = Utility.Get_MMDDHHMMSS_String(Timestamp);
            _Timestamp = UInt32.Parse(s);
            byte[] buffer = new byte[6 + 9 + _Password.Length + 10];
            Encoding.ASCII.GetBytes(_Source_Addr).CopyTo(buffer, 0);
            Encoding.ASCII.GetBytes(_Password).CopyTo(buffer, 6 + 9);
            Encoding.ASCII.GetBytes(s).CopyTo(buffer, 6 + 9 + _Password.Length);
            _AuthenticatorSource = new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);
            _Version = Version;
        }
        public byte[] ToBytes()
        {
            int i = 0;
            byte[] bytes = new byte[MessageHeader.Length + BodyLength];
            //header 12
            byte[] buffer = _Header.ToBytes();
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
            //Source_Addr 6
            i += MessageHeader.Length;
            buffer = Encoding.ASCII.GetBytes(_Source_Addr);
            Buffer.BlockCopy(buffer, 0, bytes, i, 6);
            //AuthenticatorSource 16
            i += 6;
            buffer = _AuthenticatorSource;
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //16
            //version 1
            i += 16;
            bytes[i++] = (byte)_Version; //版本
            //Timestamp
            buffer = BitConverter.GetBytes(_Timestamp);
            Array.Reverse(buffer);
            buffer.CopyTo(bytes, i);
            return (bytes);
        }
        public override string ToString()
        {
            return "[\r\n"
               + _Header.ToString() + "\r\n"
               + "\t"
               + string.Format
                 (
                  "MessageBody:"
                  + "{0}AuthenticatorSource: {1}"
                  + "{0}Password: {2}"
                  + "{0}Source_Addr: {3}"
                  + "{0}Version: {4}"
                  , "\r\n\t\t"
                  , Utility.BytesArrayToHexString(_AuthenticatorSource)
                  , _Password
                  , _Source_Addr
                  , _Timestamp
                  , _Version
                 )
               + "\r\n]";
        }
    }
    public class CMPP_CONNECT_RESP //: CMPP_Response
    {
        private MessageHeader _Header;
        public const int BodyLength = 4 + 16 + 1;
        private uint _Status;         // 4 Unsigned Integer 状态
        //   0:正确
        //   1:消息结构错
        //   2:非法源地址
        //   3:认证错
        //   4:版本太高
        //   5~:其他错误
        private byte[] _AuthenticatorISMG;      // 16 Octet String ISMG认证码,用于鉴别ISMG。
        //   其值通过单向MD5 hash计算得出,表示如下:
        //   AuthenticatorISMG =MD5(Status+AuthenticatorSource+shared secret),Shared secret 由中国移动与源地址实体事先商定,AuthenticatorSource为源地址实体发送给ISMG的对应消息CMPP_Connect中的值。
        // 认证出错时,此项为空。
        private uint _Version;         // 1 Unsigned Integer 服务器支持的最高版本号,对于3.0的版本,高4bit为3,低4位为0
        public byte[] AuthenticatorISMG
        {
            get
            {
                return _AuthenticatorISMG;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -