中国联通SGIP接口

源地址:http://blog.csdn.net/adama119/article/details/6266848

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

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

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

 

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

//文件Client.cs

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

 

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


namespace AsiaINFO.SMS.SGIP
{

    /// <summary>
    /// @Description:SGIP1.2 短消息联通网关SP客户端
    /// @Author:Adama SUN
    /// @Mail:spf193@gmail.com

    /// @Copyright (C) 2010 AsiaINFO. All rights reserved.
    /// </summary>
    public class SGIPClient : SGIPBase
    {

        public SGIPClient(Queue<byte[]> queue, SyncEvents syncEvents)
            : base(queue, syncEvents)
        {

        }


        #region private field

        private string _CorpId;           //企业代码

        private static object _SyncLockObject = new object();   //锁
        private TcpClient tc;               
        private NetworkStream _NetworkStream;


        #endregion

 

 


        #region public methos


        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="Host">主机地址</param>
        /// <param name="Port">端口</param>
        /// <param name="UserID">用户名</param>
        /// <param name="Password">密码</param>
        /// <param name="CorpId">企业代码</param>
        /// <param name="SequenceId">序列号</param>
        /// <returns></returns>
        public void Connect(string Host, int Port, string UserID, string Password,string CorpId, uint SequenceId)
        {
            this._CorpId = CorpId;

            SGIP_Bind connect = new SGIP_Bind((uint)LoginTypes.SpToSmg,UserID, Password, SequenceId);

            if (!IsConnected || tc == null || !tc.Connected)
            {
                tc = new TcpClient();
                tc.Connect(Host, Port);
                if (this._NetworkStream != null)
                {
                    try
                    {
                        this._NetworkStream.Close();
                        this._NetworkStream = null;
                    }
                    catch (Exception) { }
                }
            }

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


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

 


        /// <summary>
        /// 发送短信
        /// </summary>
        /// <param name="SPNumber">SP号码</param>
        /// <param name="feeMobile">计费手机号码</param>
        /// <param name="mobile">手机号码</param>
        /// <param name="MessageContent">短消息的内容</param>
        /// <param name="LinkID">LinkID</param>
        /// <param name="SequenceId">序列号</param>
        public void Submit(string SPNumber,string feeMobile, string mobile, string MessageContent, string LinkID, uint SequenceId)
        {
            Submit(SPNumber, feeMobile, mobile, "HELP", (uint)FeeTypes.Free, "0", (uint)SubmitMorelatetoMTFlags.NormalFirst, (uint)SubmitReportFlag.Always, MessageContent, LinkID, SequenceId);
        }

 

        /// <summary>
        /// 发送短信
        /// </summary>
        /// <param name="SPNumber">SP的接入号码</param>
        /// <param name="ChargeNumber">付费号码</param>
        /// <param name="UserNumber">接收该短消息的手机号</param>
        /// <param name="ServiceType">业务代码</param>
        /// <param name="FeeType">计费类型</param>
        /// <param name="FeeValue">费率,单位分</param>
        /// <param name="MorelatetoMTFlag">引起MT消息的原因</param>
        /// <param name="ReportFlag">状态报告标记</param>
        /// <param name="MessageContent">短消息的内容</param>
        /// <param name="LinkID">LinkID</param>
        /// <param name="SequenceId">序列号</param>
        public void Submit(string SPNumber, string ChargeNumber, string UserNumber, string ServiceType, uint FeeType, string FeeValue
            , uint MorelatetoMTFlag,uint ReportFlag, string MessageContent, string LinkID, uint SequenceId)
        {
            if (ChargeNumber != null && ChargeNumber.Length == 11)
                ChargeNumber = "86" + ChargeNumber;
            if (UserNumber != null && UserNumber.Length == 11)
                UserNumber = "86" + UserNumber;

            SGIP_SUBMIT submit = new SGIP_SUBMIT(SequenceId);
            submit.SPNumber = SPNumber;
            submit.ChargeNumber = ChargeNumber;
             // submit.ChargeNumber = "";
            submit.UserCount = 1;
            submit.UserNumber = UserNumber;
            submit.CorpId = this._CorpId;
            submit.ServiceType = ServiceType;
            submit.FeeType = FeeType;
            submit.FeeValue = FeeValue;
            submit.GivenValue = "0";
            submit.AgentFlag = (uint)SubmitAgentFlag.RealIncome;
            submit.MorelatetoMTFlag = MorelatetoMTFlag;
            submit.Priority = 0;
            submit.ExpireTime = "";
            submit.ScheduleTime = "";
            submit.ReportFlag = ReportFlag;
            submit.TP_pid = 0;
            submit.TP_udhi = 0;
            submit.MessageCoding = 15;
            submit.MessageType = 0;
            submit.MessageContent = MessageContent;
            submit.LinkID = LinkID;

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

 

        /// <summary>
        /// 断开回复
        /// </summary>
        /// <param name="SrcNodeSequence"></param>
        /// <param name="DateSequence"></param>
        /// <param name="Sequence_Id"></param>
        public void UnbindResp(uint SrcNodeSequence, uint DateSequence, uint Sequence_Id)
        {
            SGIP_Unbind_Resp response = new SGIP_Unbind_Resp(SrcNodeSequence, DateSequence, Sequence_Id);
            this.WriteToStreamWithLock(response.ToBytes(), this._NetworkStream);
        }

 

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


        #endregion


        #region private method


        private void CloseClient()
        {
            try
            {
                try
                {
                    IsConnected = false;
                    this.tc.Client.Shutdown(SocketShutdown.Both);
                }
                catch
                {
                }
            }
            finally
            {
                this.tc.Close();
            }
        }


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

                CloseClient();
                OnError(ex.Message);
            }
        }

 


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

 

        protected override void Run()
        {
            try
            {
                while (!_syncEvents.ExitThreadEvent.WaitOne(2, false))
                {
                    if (this._NetworkStream.CanRead)
                    {
                        if (this._NetworkStream.DataAvailable)
                        {
                            byte[] buffer = new byte[MessageHeader.Length]; //Header
                            buffer = this.ReadFromStreamWithLock(MessageHeader.Length, this._NetworkStream);

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

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

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                CloseClient();
                OnError("SGIPClient接收错误:"+ex.Message);
            }
            OnThreadState(ThreadState.Stopped);
            
        }
        #endregion

    }
}

 

 

 

 

 

 

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

//文件MessageEventArgs.cs

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

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

 

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

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

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

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

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

    }
}

 

 

 

 

 

 

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

//文件Server.cs

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

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

namespace AsiaINFO.SMS.SGIP
{
    /// <summary>
    /// @Description:SGIP1.2 短消息联通网关SP服务端
    /// @Author:Adama SUN
    /// @Mail:spf193@gmail.com
    /// @Copyright (C) 2010 AsiaINFO. All rights reserved.
    /// </summary>
    public class SGIPServer : SGIPBase
    {
        //     private Socket _Server;
        private TcpListener _tcpListener;
        private string _LoginName;
        private string _LoginPassowrd;
        private string _Host;
        private int _Port;
        private byte[] _Buffer = new byte[0x10000];
        private ManualResetEvent _MySet = new ManualResetEvent(false);
        private BaseSortedList<string, ClientQueue> m_ClientInfo;
        private bool m_IsRun;
        /// <summary>
        /// 空闲间隔
        /// </summary>
        private int _TerminateFreeInterval;
        /// <summary>
        /// 源节点编号
        /// </summary>
        internal static uint _SrcNodeSequence = 3057199999;

        public event NetEventDelegate RecvDataEvent;

        public SGIPServer(Queue<byte[]> queue, SyncEvents syncEvents, string Host, int Port, string LoginName, string LoginPassowrd, uint SrcNodeSequence, int rerminateFreeInterval)
            : base(queue, syncEvents)
        {
            this._Host = Host;
            this._Port = Port;
            this._LoginName = LoginName;
            this._LoginPassowrd = LoginPassowrd;
            SGIPServer._SrcNodeSequence = SrcNodeSequence;
            this.m_IsRun = true;
            this._TerminateFreeInterval = rerminateFreeInterval;
        }


        protected override void Run()
        {
            try
            {
                OnMsg("正在启动监听...");
                this.m_ClientInfo = new BaseSortedList<string, ClientQueue>();
                
               // this._Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(this._Host), this._Port);
                if (this._Host == null || this._Host == "127.0.0.1" || this._Host=="")     
                    this._tcpListener = new TcpListener(_Port);
                else
                    this._tcpListener = new TcpListener(localEP);

                this._tcpListener.Start();
                //this._Server.Bind(localEP);
                //this._Server.Listen(50);
                this.IsConnected = true;
                OnMsg("启动监听成功");
                while (!_syncEvents.ExitThreadEvent.WaitOne(2, false))
                {
                    this._MySet.Reset();
                    this._tcpListener.BeginAcceptTcpClient(new AsyncCallback(this.AcceptCallBack), this._tcpListener);
                    this._MySet.WaitOne();
                }
            }
            catch (Exception ex)
            {
                OnError("SGIPServer监听错误:" + ex.Message);
            }
            finally
            {
                Stop();
            }
        }


        public void Stop()
        {
            if (!this.IsConnected)
                return;
            try
            {
                try
                {
                    StopReceive();
                    this._tcpListener.Server.Shutdown(SocketShutdown.Both);
                }
                catch
                {
                }
            }
            finally
            {
                this._tcpListener.Server.Close();
                this.IsConnected = false;
            }
        }

 

        private void AcceptCallBack(IAsyncResult ia)
        {
            this._MySet.Set();
            try
            {
                TcpClient tc = ((TcpListener)ia.AsyncState).EndAcceptTcpClient(ia);
                ClientQueue queue = new ClientQueue(tc, DateTime.Now);
                this.m_ClientInfo.Add(this.GetSocketIP(tc), queue);
                int msgCount = tc.Client.Receive(this._Buffer);
                if (msgCount > 0)
                {
                    uint BindResult = 0;
                    if (Util.bytes2Uint(this._Buffer, 0) == msgCount)
                    {
                        if (Util.bytes2Uint(this._Buffer, 4) == 1)
                        {
                            SGIP_Bind bind = new SGIP_Bind(this._Buffer);
                            if (bind.LoginType == (uint)LoginTypes.SmgToSp || bind.LoginType == (uint)LoginTypes.SpToSmg)
                            {
                                if ((bind.LoginName == this._LoginName) && (bind.LoginPassword == this._LoginPassowrd))
                                {
                                    BindResult = 0;
                                }
                                else
                                {
                                    BindResult = 1;
                                }
                            }
                            else
                            {
                                BindResult = 4;
                            }
                            SGIP_Bind_Resp resp = new SGIP_Bind_Resp(BindResult, bind.Header.SrcNodeSequence, bind.Header.DateSequence, bind.Header.Sequence_Id);
                            this.SendMSG(resp.ToBytes(), tc);
                            if (BindResult == 0)
                            {
                                ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(this.Recv), tc);
                            }
                            else
                            {
                                string msg = string.Format("网关登录SP服务端失败 Result={0} LoginType={1} LoginName={2} Passowrd={3} ", BindResult, bind.LoginType, bind.LoginName, bind.LoginPassword);
                                OnMsg(msg);
                            }

                        }
                    }
                    else
                    {
                        this.CloseClient(tc);
                    }
                }
            }
            catch (SocketException ex)
            {
                OnError("AcceptCallBack_SocketException错误:" + ex.Message);
            }
            catch { }
        }


        public void SendMSG(byte[] bs, TcpClient tc)
        {
            try
            {
                if (tc.Client.Send(bs) == 0)
                {
                    this.CloseClient(tc);
                }
            }
            catch (SocketException)
            {
                this.CloseClient(tc);
            }
            catch { }
        }

 


        protected void Recv(object client)
        {

            string msg = string.Format("网关登录SP服务端成功 ,监听线程池分配线程ID={0}", AppDomain.GetCurrentThreadId());
            OnMsg(msg);

            TcpClient tc = null;
            NetworkStream networkStream = null;
            try
            {
                tc = (TcpClient)client;
                networkStream = tc.GetStream();
                object syncLockObject = new object();   //锁
                DateTime startTime = DateTime.Now;
                while (!_syncEvents.ExitThreadEvent.WaitOne(2, false))
                {
                    if (networkStream.CanRead)
                    {
                        if (networkStream.DataAvailable)
                        {
                            startTime = DateTime.Now;
                            byte[] buffer = new byte[MessageHeader.Length]; //Header
                            buffer = this.ReadFromStreamWithLock(syncLockObject, MessageHeader.Length, networkStream);

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

                            int l = (int)header.Total_Length - MessageHeader.Length;
                            if (l > 0)
                            {
                                buffer = this.ReadFromStreamWithLock(syncLockObject, l, networkStream);
                                Buffer.BlockCopy(buffer, 0, bytes, MessageHeader.Length, buffer.Length);
                            }

                            if (this.RecvDataEvent != null)
                            {
                                this.RecvDataEvent(bytes, 0, tc);
                            }

                        }
                        else
                        {
                            ///计算空闲时间
                            TimeSpan ts = DateTime.Now - startTime;
                            if (ts.TotalSeconds > this._TerminateFreeInterval)
                            {
                                Terminate(syncLockObject, 1, networkStream);
                                CloseClient(tc);
                                msg = string.Format("超时:监听线程池 线程ID={0}", AppDomain.GetCurrentThreadId());
                                OnMsg(msg);
                                break;
                            }
                        }
                    }
                    else
                        break;
                }
            }
            catch (Exception)
            {
                CloseClient(tc);
                msg = string.Format("接收错误:监听线程池 线程ID={0}", AppDomain.GetCurrentThreadId());
                OnMsg(msg);
            }
            finally
            {
                msg = string.Format("退出:监听线程池 线程ID={0}", AppDomain.GetCurrentThreadId());
                OnMsg(msg);
            }
            
            
          
        }

 


        /// <summary>
        /// 中断
        /// </summary>
        /// <param name="SequenceId"></param>
        public void Terminate(object syncLockObject,uint SequenceId, NetworkStream stream)
        {
            MessageHeader terminate = new MessageHeader(MessageHeader.Length, SGIP_Command_Id.SGIP_UNBIND, SequenceId);
            this.WriteToStreamWithLock(syncLockObject,terminate.ToBytes(), stream);
        }

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

 

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


        private void CloseClient(TcpClient tc)
        {
            try
            {
                try
                {
                    tc.Client.Shutdown(SocketShutdown.Both);
                }
                catch
                {
                }
            }
            finally
            {
                tc.Close();
            }
        }


        private string GetSocketIP(TcpClient tc)
        {
            try
            {
                IPEndPoint remoteEndPoint = (IPEndPoint)tc.Client.RemoteEndPoint;
                return (remoteEndPoint.Address.ToString() + ":" + remoteEndPoint.Port.ToString());
            }
            catch
            {
                return "";
            }
        }


        private BaseSortedList<string, ClientQueue> ClientInfo
        {
            get
            {
                return this.m_ClientInfo;
            }
        }

 


        /// <summary>
        /// 发送SGIP_DELIVER_RESP
        /// </summary>
        /// <param name="Result"></param>
        /// <param name="SrcNodeSequence"></param>
        /// <param name="DateSequence"></param>
        /// <param name="SequenceId"></param>
        /// <param name="soc"></param>
        public void DeliverResp(uint Result, uint SrcNodeSequence, uint DateSequence, uint SequenceId, TcpClient tc)
        {
            SGIP_DELIVER_RESP deliverResp = new SGIP_DELIVER_RESP(Result, "", SrcNodeSequence, DateSequence, SequenceId);
            this.SendMSG(deliverResp.ToBytes(), tc);
        }

        /// <summary>
        /// 发送SGIP_Report_Resp
        /// </summary>
        /// <param name="Result"></param>
        /// <param name="SrcNodeSequence"></param>
        /// <param name="DateSequence"></param>
        /// <param name="SequenceId"></param>
        /// <param name="soc"></param>
        public void ReportResp(uint Result, uint SrcNodeSequence, uint DateSequence, uint SequenceId, TcpClient tc)
        {
            SGIP_Report_Resp reportResp = new SGIP_Report_Resp(Result, "", SrcNodeSequence, DateSequence, SequenceId);
            this.SendMSG(reportResp.ToBytes(), tc);
        }

 

        /// <summary>
        /// 发送SGIP_Unbind_Resp
        /// </summary>
        /// <param name="SrcNodeSequence"></param>
        /// <param name="DateSequence"></param>
        /// <param name="SequenceId"></param>
        /// <param name="soc"></param>
        public void UnbindResp(uint SrcNodeSequence, uint DateSequence, uint SequenceId, TcpClient tc)
        {
            SGIP_Unbind_Resp unbindResp = new SGIP_Unbind_Resp(SrcNodeSequence, DateSequence, SequenceId);
            this.SendMSG(unbindResp.ToBytes(), tc);
            CloseClient(tc);
        }

    }

    public delegate void NetEventDelegate(byte[] bs, int recvCount, TcpClient tc);
}

 

 

 

 

 

 

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

//文件SGIPBase.cs

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

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Collections;
namespace AsiaINFO.SMS.SGIP
{
    public class SGIPBase
    {
        public delegate void MsgEventDelegate(string msg);
        /// <summary>
        /// 线程状态通知
        /// </summary>
        /// <param name="sender">线程</param>
        /// <param name="state">线程状态</param>
        public delegate void ThreadStateDelegate(object sender, ThreadState state);

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

        #region public property

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


        #endregion

 

        #region protected field

        protected Queue<byte[]> _receiveQueue;//接收队列
        protected SyncEvents _syncEvents;//信号
        protected Thread _thread;
        private object _syncIsConnectedObject = new object();
        private bool _IsConnected = false;      //监听或连接状态
        #endregion

 

        #region public event

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

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

 


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

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

        #endregion


        #region public method


        public void StartRun()
        {

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

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

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

 


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


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


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

        }


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

        #endregion

 

        #region protected method

 


        protected virtual void Run()
        {

        }

        #endregion
    }
}

 

 

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

//文件SGIPMessages.cs

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

 

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

namespace AsiaINFO.SMS.SGIP
{
    //SGIP 消息定义 
    public enum SGIP_Command_Id : uint
    {
        SGIP_BIND = 0x1,
        SGIP_BIND_RESP = 0x80000001,
        SGIP_UNBIND = 0x2,
        SGIP_UNBIND_RESP = 0x80000002,
        SGIP_SUBMIT = 0x3,
        SGIP_SUBMIT_RESP = 0x80000003,
        SGIP_DELIVER = 0x4,
        SGIP_DELIVER_RESP = 0x80000004,
        SGIP_REPORT = 0x5,
        SGIP_REPORT_RESP = 0x80000005,
        //SGIP_ADDSP = 0x6,
        //SGIP_ADDSP_RESP = 0x80000006,
        //SGIP_MODIFYSP = 0x7,
        //SGIP_MODIFYSP_RESP = 0x80000007,
        //SGIP_DELETESP = 0x8,
        //SGIP_DELETESP_RESP = 0x80000008,
        //SGIP_QUERYROUTE = 0x9,
        //SGIP_QUERYROUTE_RESP = 0x80000009,
        //SGIP_ADDTELESEG = 0xa,
        //SGIP_ADDTELESEG_RESP = 0x8000000a,
        //SGIP_MODIFYTELESEG = 0xb,
        //SGIP_MODIFYTELESEG_RESP = 0x8000000b,
        //SGIP_DELETETELESEG = 0xc,
        //SGIP_DELETETELESEG_RESP = 0x8000000c,
        //SGIP_ADDSMG = 0xd,
        //SGIP_ADDSMG_RESP = 0x8000000d,
        //SGIP_MODIFYSMG = 0xe,
        //SGIP_MODIFYSMG_RESP = 0x0000000e,
        //SGIP_DELETESMG = 0xf,
        //SGIP_DELETESMG_RESP = 0x8000000f,
        //SGIP_CHECKUSER = 0x10,
        //SGIP_CHECKUSER_RESP = 0x80000010,
        //SGIP_USERRPT = 0x11,
        //SGIP_USERRPT_RESP = 0x80000011,
        //SGIP_TRACE = 0x1000,
        //SGIP_TRACE_RESP = 0x80001000,
    }

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

        /// <summary>
        /// 获取命令类型
        /// </summary>
        public SGIP_Command_Id Command_Id
        {
            get
            {
                return this._Command_Id;
            }
        }

        /// <summary>
        /// 获取序列号
        /// </summary>
        public uint Sequence_Id
        {
            get
            {
                return this._Sequence_Id;
            }
        }


        /// <summary>
        /// 获取原节点
        /// </summary>
        public uint SrcNodeSequence
        {
            get { return _SrcNodeSequence; }
        }

        /// <summary>
        /// 获取命令产生的日期和时间
        /// </summary>
        public uint DateSequence
        {
            get { return _DateSequence; }
        }

        /// <summary>
        /// 获取总长度
        /// </summary>
        public uint Total_Length
        {
            get
            {
                return this._Total_Length;
            }
        }

 


        private uint _Total_Length;    // 4 Unsigned Integer 消息总长度(含消息头及消息体) 
        private SGIP_Command_Id _Command_Id; // 4 Unsigned Integer 命令或响应类型 
        private uint _SrcNodeSequence = 3057199999;  //4 Unsigned Integer 源节点的编号
        private uint _DateSequence = 0;     //4 Unsigned Integer 格式为十进制的mmddhhmmss
        private uint _Sequence_Id;    // 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)


        public MessageHeader
         (
          uint Total_Length
          , SGIP_Command_Id Command_Id
          , uint Sequence_Id
         ) //发送前 
        {
            this._Total_Length = Total_Length;
            this._Command_Id = Command_Id;
            this._SrcNodeSequence = SGIPServer._SrcNodeSequence;
            this._DateSequence = uint.Parse(Util.Get_MMDDHHMMSS_String(DateTime.Now));
            this._Sequence_Id = Sequence_Id;
        }


        public MessageHeader
         (
          uint Total_Length
          , SGIP_Command_Id Command_Id
          , uint SrcNodeSequence
          , uint  DateSequence
          , uint Sequence_Id
         ) //发送前 
        {
            this._Total_Length = Total_Length;
            this._Command_Id = Command_Id;
            this._SrcNodeSequence = SrcNodeSequence;
            this._DateSequence = DateSequence;
            this._Sequence_Id = Sequence_Id;
        }

 

 

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

            i += 4;
            Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._Command_Id = (SGIP_Command_Id)BitConverter.ToUInt32(buffer, 0);


            i += 4;
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._SrcNodeSequence = BitConverter.ToUInt32(buffer, 0);


            i += 4;
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._DateSequence = BitConverter.ToUInt32(buffer, 0);


            i += 4;
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            Array.Reverse(buffer);
            this._Sequence_Id = BitConverter.ToUInt32(buffer, 0);

 

        }


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

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

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

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

            i += 4;
            buffer = BitConverter.GetBytes(this._DateSequence);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, i, 4);

            i += 4;
            buffer = BitConverter.GetBytes(this._Sequence_Id);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, i, 4);

            return bytes;
        }
        public override string ToString()
        {
            return string.Format("MessageHeader: tCommand_Id={0}    tSequence_Id={1}    tTotal_Length={2}"
              , this._Command_Id
              , this._Sequence_Id
              , this._Total_Length
             );

        }

    }

    public class SGIP_Bind        //  双向
    {
        public const int BodyLength = 1 + 16 + 16 + 8;

        private uint _LoginType;      // 1 Unsigned Integer 登录类型。
        private string _LoginName;      // 16 Octet String  服务器端给客户端分配的登录名
        private string _LoginPassword;  // 16 Octet String  服务器端和Login Name对应的密码
        private string _Reserve;        // 8 Octet String  保留,扩展用

        private MessageHeader _Header;

        public SGIP_Bind
         (
          uint LoginType
          , string LoginName
          , string LoginPassword
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length + BodyLength, SGIP_Command_Id.SGIP_BIND, Sequence_Id);

            this._LoginType = LoginType;
            this._LoginName = LoginName;
            this._LoginPassword = LoginPassword;
            this._Reserve = "";
        }

        //public SGIP_Bind
        // (
        //  uint LoginType
        //  , string LoginName
        //  , string LoginPassword
        //  , uint SrcNodeSequence
        //  , uint DateSequence
        //  , uint Sequence_Id
        // )
        //{
        //    this._Header = new MessageHeader(MessageHeader.Length + BodyLength, SGIP_Command_Id.SGIP_BIND,SrcNodeSequence,DateSequence, Sequence_Id);

        //    this._LoginType = LoginType;
        //    this._LoginName = LoginName;
        //    this._LoginPassword = LoginPassword;
        //    this._Reserve = "";
        //}

 

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


            //LoginType 1 
            i += MessageHeader.Length;
            this._LoginType = (uint)bytes[i++];

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


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

 

            //LoginPassword 16
            i += 16;
            buffer = new byte[8];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._Reserve = s;
        }

 

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

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

            //LoginType 1
            i += MessageHeader.Length;
            bytes[i++] = (byte)this._LoginType;

            //LoginName 16 
            buffer = Encoding.ASCII.GetBytes(this._LoginName);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //LoginPassword 16 
            i += 16;
            buffer = Encoding.ASCII.GetBytes(this._LoginPassword);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);


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

        public override string ToString()
        {
            return string.Format("Header={0}    LoginType={1}    LoginName={2}    LoginPassword={3}    Reserve={4}"
                , this._Header.ToString()
                , this._LoginType
                , this._LoginName
                , this._LoginPassword
                , this._Reserve);
        }


        /// <summary>
        /// 获取 登录类型
        /// </summary>
        public uint LoginType
        {
            get { return _LoginType; }
        }


        /// <summary>
        /// 获取登陆用户名
        /// </summary>
        public string LoginName
        {
            get { return _LoginName; }
        }


        /// <summary>
        /// 获取登陆密码
        /// </summary>
        public string LoginPassword
        {
            get { return _LoginPassword; }
        }

 

        /// <summary>
        /// 获取保留信息
        /// </summary>
        public string Reserve
        {
            get { return _Reserve; }
        }

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


    }

    public class SGIP_Bind_Resp // 双向 
    {
        private MessageHeader _Header;
        public const int BodyLength = 1 + 8;

        private uint _Result;       // 1 Unsigned Integer 执行命令是否成功  0:执行成功  其它:错误码
        private string _Reserve;    // 8 Octet String  保留,扩展用


        public SGIP_Bind_Resp
         (
          uint Result
          , uint SrcNodeSequence
          , uint DateSequence
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length + BodyLength, SGIP_Command_Id.SGIP_BIND_RESP, SrcNodeSequence, DateSequence, Sequence_Id);

            this._Result = Result;
            this._Reserve = "null";
        }


        public SGIP_Bind_Resp(byte[] bytes)
        {
            //header 20
            int i = 0;
            string s = null;
            byte[] buffer = new byte[MessageHeader.Length];
            Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
            this._Header = new MessageHeader(buffer);


            //Result 1 
            i += MessageHeader.Length;
            this._Result = (uint)bytes[i++];

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

        }

 

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

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

            //Result 1
            i += MessageHeader.Length;
            bytes[i++] = (byte)this._Result;

            //Result 8
            buffer = Encoding.ASCII.GetBytes(this._Reserve);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
            return (bytes);

 


        }


        public override string ToString()
        {
            return string.Format("Header={0}   Result={1}    Reserve={2}"
                , this._Header.ToString()
                , this._Result
                , this._Reserve);

        }


        /// <summary>
        /// 获取结果
        /// </summary>
        public uint Result
        {
          get { return _Result; }
        }

        /// <summary>
        /// 获取保留信息
        /// </summary>
        public string Reserve
        {
          get { return _Reserve; }
        }

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

    }

    public class SGIP_SUBMIT   
    {
        private int _BodyLength;

        public const int FixedBodyLength = 21   //SPNumber
                 + 21   //ChargeNumber
                 + 1    //UserCount
                 +21    //UserNumber
                 + 5    //CorpId
                 + 10   //ServiceType
                 + 1    //FeeType
                 + 6    //FeeValue
                 + 6    //GivenValue
                 + 1    //AgentFlag
                 + 1    //MorelatetoMTFlag
                 + 1    //Priority
                 + 16   //ExpireTime
                 + 16   //ScheduleTime
                 + 1    //ReportFlag
                 + 1    //TP_pid
                 + 1    //TP_udhi
                 + 1    //MessageCoding
                 + 1    //MessageType
                 + 4    //MessageLength
            //+ Message Length  //MessageContent
                 + 8 ;   //Reserve

        private string _SPNumber;       //21 Octet String   SP的接入号码
        private string _ChargeNumber;   //21 Octet String   付费号码,手机号码前加“86”国别标志
        private uint _UserCount;        //1 Unsigned Integer 接收短消息的手机数量,取值范围1至100
        private string _UserNumber;     //21 Octet String   接收该短消息的手机号 手机号码前加“86”国别标志
        private string _CorpId;         //5  Octet String  企业代码,取值范围0-99999
        private string _ServiceType;    //10  Octet String  业务代码,由SP定义
        private uint _FeeType;          //1 Unsigned Integer 计费类型
        private string _FeeValue;       //6  Octet String  取值范围0-99999,该条短消息的收费值,单位为分,由SP定义对于包月制收费的用户,该值为月租费的值
        private string _GivenValue;     //6  Octet String  赠送用户的话费,单位为分
        private uint _AgentFlag;        //1 Unsigned Integer  代收费标志,0:应收;1:实收
        private uint _MorelatetoMTFlag;  //1 Unsigned Integer   引起MT消息的原因
        private uint _Priority;         //1 Unsigned Integer   优先级0-9从低到高,默认为0
        private string _ExpireTime;     //16  Octet String     短消息寿命的终止时间,如果为空,表示使用短消息中心的缺省值
        private string _ScheduleTime;   //16  Octet String     短消息定时发送的时间,如果为空,表示立刻发送该短消息
        private uint _ReportFlag;       //1 Unsigned Integer    状态报告标记
        private uint _TP_pid;           //1 Unsigned Integer
        private uint _TP_udhi;          //1 Unsigned Integer
        private uint _MessageCoding;    //1 Unsigned Integer    短消息的编码格式
        private uint _MessageType;      //1 Unsigned Integer    信息类型:0-短消息信息  其它:待定
        private uint _MessageLength;    //4 Unsigned Integer    短消息的长度
        private string _MessageContent;    // MessageLength Octet String 信息内容。 
        private string _LinkID;
        
        private MessageHeader _Header;
        private uint _Sequence_Id;

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

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

            this._MessageLength = (uint)_Msg_Content_Bytes.Length;
            this._BodyLength = (int)(FixedBodyLength + this._MessageLength);
            this._Header = new MessageHeader((uint)(MessageHeader.Length + this._BodyLength), SGIP_Command_Id.SGIP_SUBMIT, this._Sequence_Id);
        }

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

            //SPNumber //21
            buffer = Encoding.ASCII.GetBytes(this._SPNumber);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //ChargeNumber //21
            i += 21;
            buffer = Encoding.ASCII.GetBytes(this._ChargeNumber);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //UserCount //1
            i += 21;
            bytes[i++] = (byte)this._UserCount;

            //UserNumber //21
            buffer = Encoding.ASCII.GetBytes(this._UserNumber);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //CorpId    //5
            i += 21;
            buffer = Encoding.ASCII.GetBytes(this._CorpId);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //ServiceType;    //10
            i += 5;
            buffer = Encoding.ASCII.GetBytes(this._ServiceType);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //FeeType          //1
            i += 10;
            bytes[i++] = (byte)this._FeeType;

            //FeeValue   //6
            buffer = Encoding.ASCII.GetBytes(this._FeeValue);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //GivenValue    //6
            i += 6;
            buffer = Encoding.ASCII.GetBytes(this._GivenValue);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            i += 6;
            bytes[i++] = (byte)this._AgentFlag;
            bytes[i++] = (byte)this._MorelatetoMTFlag;
            bytes[i++] = (byte)this._Priority;

            //ExpireTime;     //16 
            buffer = Encoding.ASCII.GetBytes(this._ExpireTime);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

            //ScheduleTime;   //16 
            i += 16;
            buffer = Encoding.ASCII.GetBytes(this._ScheduleTime);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);


            i += 16;
            bytes[i++] = (byte)this._ReportFlag;
            bytes[i++] = (byte)this._TP_pid;
            bytes[i++] = (byte)this._TP_udhi;
            bytes[i++] = (byte)this._MessageCoding;
            bytes[i++] = (byte)this._MessageType;


            //MessageLength //4
            buffer = BitConverter.GetBytes(this._MessageLength);
            Array.Reverse(buffer);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);


            //Msg_Content 
            i += 4;
            Buffer.BlockCopy(this._Msg_Content_Bytes, 0, bytes, i, this._Msg_Content_Bytes.Length);

            //LinkID 
            i += (int)this._MessageLength;
            buffer = Encoding.ASCII.GetBytes(this._LinkID);
            Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
            return bytes;
        }


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


        /// <summary>
        /// SP的接入号码
        /// </summary>
        public string SPNumber
        {
            get { return _SPNumber; }
            set { _SPNumber = value; }
        }
        /// <summary>
        /// 付费号码,设置时自动在号码前加“86”
        /// </summary>
        public string ChargeNumber
        {
            get { return _ChargeNumber; }
            set { _ChargeNumber = value; }
        }
        /// <summary>
        /// 接收短消息的手机数量 ,必须为1
        /// </summary>
        public uint UserCount
        {
            get { return _UserCount; }
            set { _UserCount = value; }
        }
        /// <summary>
        /// 接收该短消息的手机号,设置时自动在号码前加“86”
        /// </summary>
        public string UserNumber
        {
            get { return _UserNumber; }
            set {
                
                _UserNumber =value; 
            }
        }
        /// <summary>
        /// 企业代码
        /// </summary>
        public string CorpId
        {
            get { return _CorpId; }
            set { _CorpId = value; }
        }
        /// <summary>
        /// 业务代码,由SP定义
        /// </summary>
        public string ServiceType
        {
            get { return _ServiceType; }
            set { _ServiceType = value; }
        }
        /// <summary>
        /// 计费类型
        /// </summary>
        public uint FeeType
        {
            get { return _FeeType; }
            set { _FeeType = value; }
        }
        /// <summary>
        /// 该条短消息的收费值,单位为分
        /// </summary>
        public string FeeValue
        {
            get { return _FeeValue; }
            set { _FeeValue = value; }
        }

        public string GivenValue
        {
            get { return _GivenValue; }
            set { _GivenValue = value; }
        }
        /// <summary>
        /// 代收费标志,0:应收;1:实收
        /// </summary>
        public uint AgentFlag
        {
            get { return _AgentFlag; }
            set { _AgentFlag = value; }
        }
        /// <summary>
        /// 引起MT消息的原因
        /// </summary>
        public uint MorelatetoMTFlag
        {
            get { return _MorelatetoMTFlag; }
            set { _MorelatetoMTFlag = value; }
        }
        /// <summary>
        /// 优先级
        /// </summary>
        public uint Priority
        {
            get { return _Priority; }
            set { _Priority = value; }
        }

        /// <summary>
        /// 短消息寿命的终止时间
        /// </summary>
        public string ExpireTime
        {
            get { return _ExpireTime; }
            set { _ExpireTime = value; }
        }


        /// <summary>
        /// 短消息定时发送的时间
        /// </summary>
        public string ScheduleTime
        {
            get { return _ScheduleTime; }
            set { _ScheduleTime = value; }
        }


        /// <summary>
        /// 状态报告标记
        /// </summary>
        public uint ReportFlag
        {
            get { return _ReportFlag; }
            set { _ReportFlag = 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; }
        }


        /// <summary>
        /// 短消息的编码格式
        /// </summary>
        public uint MessageCoding
        {
            get { return _MessageCoding; }
            set {
                _MessageCoding = value;
                if (this._MessageContent != null)
                {
                    this.SetHeader();
                }
            }
        }

 

        /// <summary>
        /// 信息类型:0-短消息信息  其它:待定
        /// </summary>
        public uint MessageType
        {
            get { return _MessageType; }
            set { _MessageType = value; }
        }


        /// <summary>
        /// 短消息的长度
        /// </summary>
        public uint MessageLength
        {
            get { return _MessageLength; }
            set { _MessageLength = value; }
        }
        /// <summary>
        /// 短消息的内容
        /// </summary>
        public string MessageContent
        {
            get
            {
                return this._MessageContent;
            }
            set
            {
                this._MessageContent = value;
                this.SetHeader();
            }
        }

        public string LinkID
        {
            get { return _LinkID; }
            set { _LinkID = value; }
        }


        public override string ToString()
        {
            return "[/r/n"
               + this._Header.ToString() + "/r/n"
               + string.Format
               (
                "/tMessageBody:"
                + "/r/n/t/tSPNumber: {0}"
                + "/r/n/t/tChargeNumber: {1}"
                + "/r/n/t/tUserCount: {2}"
                + "/r/n/t/tUserNumber: {3}"
                + "/r/n/t/tCorpId: {4}"
                + "/r/n/t/tServiceType {5}"
                + "/r/n/t/tFeeType: {6}"
                + "/r/n/t/tFeeValue: {7}"
                + "/r/n/t/tGivenValue: {8}"
                + "/r/n/t/tAgentFlag: {9}"
                + "/r/n/t/tMorelatetoMTFlag {10}"
                + "/r/n/t/tPriority: {11}"
                + "/r/n/t/tExpireTime: {12}"
                + "/r/n/t/tScheduleTime: {13}"
                + "/r/n/t/tReportFlag: {14}"
                + "/r/n/t/tTP_pid: {15}"
                + "/r/n/t/tTP_udhi: {16}"
                + "/r/n/t/tMessageCoding: {17}"
                + "/r/n/t/tMessageType: {18}"
                + "/r/n/t/tMessageLength: {19}"
                + "/r/n/t/tMessageContent: {20}"
                + "/r/n/t/tlinkID: {21}"
                + "/r/n/t/tSequence_Id: {22}"
                , this._SPNumber
                , this._ChargeNumber
                , this._UserCount
                , this._UserNumber
                , this._CorpId
                , this._ServiceType
                , this._FeeType
                , this._FeeValue
                , this._GivenValue
                , this._AgentFlag
                , this._MorelatetoMTFlag
                , this._Priority
                , this._ExpireTime
                , this._ScheduleTime
                , this._ReportFlag
                , this._TP_pid
                , this._TP_udhi
                , this._MessageCoding
                , this._MessageType
                , this._MessageLength
                , this._MessageContent
                , this._LinkID
                , this._Sequence_Id
               )
             + "/r/n]";
        }

    }

    public class SGIP_SUBMIT_RESP  
    {
        private MessageHeader _Header;
        private uint _Result;
        private string _Reserve;

        public const int BodyLength = 1 + 8;

        public uint Result
        {
            get
            {
                return this._Result;
            }
        }

        public string Reserve
        {
            get
            {
                return this._Reserve;
            }
        }

        public MessageHeader Header
        {
            get
            {

                return this._Header;
            }
        }

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

            //Result 
            i += MessageHeader.Length;
            this._Result = (uint)bytes[i++];

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


        }
        public override string ToString()
        {
            return "[/r/n"
             + this._Header.ToString() + "/r/n"
             + string.Format
              (
               "/tMessageBody:"
               + "/r/n/t/tResult: {0}"
               + "/r/n/t/tReserve: {1}"

               , this._Result
               , this._Reserve
              )
             + "/r/n]";
        }
    }

    public class SGIP_DELIVER  
    {

        private MessageHeader _Header;

        private string _UserNumber; //发送短消息的用户手机号,手机号码前加“86”国别标志
        private string _SPNumber;   //SP的接入号码
        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 _MessageCoding;
        private uint _MessageLength;
        private string _MessageContent;
        private string _LinkID;

 

        public const int FixedBodyLength = 21 // UserNumber Octet String    信息标识。
                + 21    // SPNumber Octet String SP的接入号码
                 + 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    // MessageCoding  Unsigned Integer
                 + 4    // MessageLength Unsigned Integer
            //+Message Length // MessageLength Octet String 消息内容。 
                + 8;      //LinkID Octet String
 
        private int _BodyLength;
        public int BodyLength
        {
            get{return this._BodyLength;}
        }

        public SGIP_DELIVER(byte[] bytes)
        {
            int i = 0;
            string s = null;

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

            //UserNumber 21
            i += MessageHeader.Length;
            buffer = new byte[21];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            if (s != null && s.Length > 11 && s.Substring(0, 2) == "86")
                s = s.Substring(2, s.Length - 2);
            this._UserNumber = s;


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

 

            //
            i += 21;
            this._TP_pid = (uint)bytes[i++];
            this._TP_udhi = (uint)bytes[i++];
            this._MessageCoding = (uint)bytes[i++];


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

 

            //MessageContent 
            i += 4;
            buffer = new byte[this._MessageLength];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            switch (this._MessageCoding)
            {
                case 8:
                    this._MessageContent = Encoding.BigEndianUnicode.GetString(buffer).Trim();
                    break;
                case 15: //gb2312 
                    this._MessageContent = Encoding.GetEncoding("gb2312").GetString(buffer).Trim();
                    break;
                case 0: //ascii 
                case 3: //短信写卡操作 
                case 4: //二进制信息 
                default:
                    this._MessageContent = Encoding.ASCII.GetString(buffer).ToString();
                    break;
            }

            //Linkid 8 
            i += (int)this._MessageLength;
            buffer = new byte[8];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if(s.IndexOf('/0')>0)
                s = s.Substring(0, s.IndexOf('/0'));
            this._LinkID = s;

        }


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

        public string UserNumber
        {
            get { return _UserNumber; }
        }


        public string SPNumber
        {
            get { return _SPNumber; }
        }


        public uint TP_pid
        {
            get { return _TP_pid; }
        }


        public uint TP_udhi
        {
            get { return _TP_udhi; }
            set { _TP_udhi = value; }
        }


        public uint MessageCoding
        {
            get { return _MessageCoding; }
        }

 

        public uint MessageLength
        {
            get { return _MessageLength; }
        }

 

        public string MessageContent
        {
            get { return _MessageContent; }
        }


        public string LinkID
        {
            get { return _LinkID; }
        }


        public override string ToString()
        {
            return "[/r/n"
             + this._Header.ToString() + "/r/n"
             + string.Format
              (
               "/tMessageBody:"
               + "/r/n/t/tBodyLength: {0}"
               + "/r/n/t/tUserNumber: {1}"
               + "/r/n/t/tTP_pid: {2}"
               + "/r/n/t/tTP_udhi: {3}"
               + "/r/n/t/tMessageCoding: {4}"
               + "/r/n/t/tMessageLength: {5}"
               + "/r/n/t/tMessageContent: {6}"
               + "/r/n/t/tLinkID: {7}"
               , this._BodyLength
               , this._SPNumber
               , this._TP_pid
               , this._TP_udhi
               , this._MessageCoding
               , this._MessageLength
               , this._MessageContent
               , this._LinkID
              )
             + "/r/n]";
        }


    }

    public class SGIP_DELIVER_RESP  
    {
        public const int Bodylength = 1 + 8;
        private MessageHeader _Header;

        private uint _Result;
        private string _Reserve;

        public SGIP_DELIVER_RESP
        (
          uint Result
          , string Reserve
          , uint SrcNodeSequence
          , uint DateSequence
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length + Bodylength, SGIP_Command_Id.SGIP_DELIVER_RESP,SrcNodeSequence,DateSequence,Sequence_Id);
            this._Result = Result;
            this._Reserve = Reserve;
        }

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

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

            //Result 1 
            bytes[i++] = (byte)this._Result;

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

        }


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

    }

    public class SGIP_Report  
    {
        public const int BodyLength = 12 + 1 + 21 + 1 + 1 + 8;
        private MessageHeader _Header;

        private uint _SrcNodeSequence;  //4 Unsigned Integer 源节点的编号
        private uint _DateSequence;     //4 Unsigned Integer 格式为十进制的mmddhhmmss
        private uint _Sequence_Id;    // 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)

        private uint _ReportType;       //1 Unsigned Integer Report命令类型    0:对先前一条Submit命令的状态报告   1:对先前一条前转Deliver命令的状态报告
        private string _UserNumber;     //21 Octet String 接收短消息的手机号,手机号码前加“86”国别标志
        private uint _State;            //1 Unsigned Integer 该命令所涉及的短消息的当前执行状态 0:发送成功 1:等待发送 2:发送失败
        private uint _ErrorCode;        //1 Unsigned Integer 当State=2时为错误码值,否则为0
        private string _Reserve;        //8 Octet String保留,扩展用


        public SGIP_Report(byte[] bytes)
        {
            int i = 0;
            string s = null;

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

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

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


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

            //ReportType 1
            i += 4;
            this._ReportType = (uint)bytes[i++];

            //UserNumber 21
            buffer = new byte[21];
            Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
            s = Encoding.ASCII.GetString(buffer).Trim();
            if (s.IndexOf('/0') > 0)
                s = s.Substring(0, s.IndexOf('/0'));
            if (s != null && s.Length > 11 && s.Substring(0, 2) == "86")
                s = s.Substring(2, s.Length - 2);
            this._UserNumber = s;


            //State 1
            i += 21;
            this._State = (uint)bytes[i++];
            this._ErrorCode = (uint)bytes[i++];


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


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

        /// <summary>
        /// 获取原节点
        /// </summary>
        public uint SrcNodeSequence
        {
            get { return _SrcNodeSequence; }
        }

        /// <summary>
        /// 获取命令产生的日期和时间
        /// </summary>
        public uint DateSequence
        {
            get { return _DateSequence; }
        }


        /// <summary>
        /// 获取序列号
        /// </summary>
        public uint Sequence_Id
        {
            get{return this._Sequence_Id;}
        }

 

        /// <summary>
        /// Report命令类型
        /// </summary>
        public uint ReportType
        {
            get { return _ReportType; }
        }

        /// <summary>
        /// 接收短消息的手机号,手机号码前加“86”国别标志
        /// </summary>
        public string UserNumber
        {
            get { return _UserNumber; }
        }

        /// <summary>
        /// 该命令所涉及的短消息的当前执行状态 0:发送成功 1:等待发送 2:发送失败
        /// </summary>
        public uint State
        {
            get { return _State; }
        }

        /// <summary>
        /// 当State=2时为错误码值,否则为0
        /// </summary>
        public uint ErrorCode
        {
            get { return _ErrorCode; }
        }


        public string Reserve
        {
            get { return _Reserve; }
        }


        public override string ToString()
        {
            return string.Format
              (
               "[/r/nMessageBody:"
               + "/r/n/tBodyLength: {0}"
               + "/r/n/tSrcNodeSequence: {1}"
               + "/r/n/tDateSequence: {2}"
               + "/r/n/tSequence_Id: {3}"
               + "/r/n/tReportType: {4}"
               + "/r/n/tUserNumber: {5}"
               + "/r/n/tState {6}"
               + "/r/n/tErrorCode {7}"
               + "/r/n/tReserve {8}"
               + "/r/n]"
               , SGIP_Report.BodyLength
               , this._SrcNodeSequence
               , this._DateSequence
               , this._Sequence_Id
               , this._ReportType
               , this._UserNumber
               , this._State
               , this._ErrorCode
               , this._Reserve
              );
        }
    }

    public class SGIP_Report_Resp
    {
        public const int Bodylength = 1 + 8;
        private MessageHeader _Header;

        private uint _Result;
        private string _Reserve;


        public SGIP_Report_Resp
        (
          uint Result
          , string Reserve
          , uint SrcNodeSequence
          , uint DateSequence
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length + Bodylength, SGIP_Command_Id.SGIP_REPORT_RESP, SrcNodeSequence, DateSequence, Sequence_Id);
            this._Result = Result;
            this._Reserve = Reserve;
        }

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

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

            //Result 1 
            bytes[i++] = (byte)this._Result;

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

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

    }

    public class SGIP_Unbind_Resp
    {
        private MessageHeader _Header;

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


        public SGIP_Unbind_Resp
        (
           uint SrcNodeSequence
          , uint DateSequence
          , uint Sequence_Id
         )
        {
            this._Header = new MessageHeader(MessageHeader.Length, SGIP_Command_Id.SGIP_UNBIND_RESP,SrcNodeSequence,DateSequence,Sequence_Id);
        }


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

    }
}

 

 

 

 

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

//文件StateDictionary.cs

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

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

namespace AsiaINFO.SMS.SGIP
{

    /// <summary>
    /// 状态字典
    /// </summary>
    public class StateDictionary
    {
        
        /// <summary>
        /// Status 请求返回结果。响应包用来向请求包返回成功信息或者失败原因。
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public static string stateRespDictionary(uint state)
        {
            string result = "结果:";
            switch (state)
            {
                case 0: result += "无错误,命令正确接收"; break;
                case 1: result += "非法登录,如登录名、口令出错、登录名与口令不符等。"; break;
                case 2: result += "重复登录,如在同一TCP/IP连接中连续两次以上请求登录。"; break;
                case 3: result += "连接过多,指单个节点要求同时建立的连接数过多。"; break;
                case 4: result += "登录类型错,指bind命令中的logintype字段出错。"; break;

                case 5: result += "参数格式错,指命令中参数值与参数类型不符或与协议规定的范围不符。"; break;
                case 6: result += "非法手机号码,协议中所有手机号码字段出现非86130号码或手机号码前未加“86”时都应报错。"; break;
                case 7: result += "消息ID错"; break;
                case 8: result += "信息长度错"; break;
                case 9: result += "非法序列号,包括序列号重复、序列号格式错误等"; break;
                case 10: result += "非法操作GNS"; break;
                case 11: result += "节点忙,指本节点存储队列满或其他原因,暂时不能提供服务的情况"; break;

                case 21: result += "目的地址不可达,指路由表存在路由且消息路由正确但被路由的节点暂时不能提供服务的情况"; break;
                case 22: result += "路由错,指路由表存在路由但消息路由出错的情况,如转错SMG等"; break;
                case 23: result += "路由不存在,指消息路由的节点在路由表中不存在"; break;
                case 24: result += "计费号码无效,鉴权不成功时反馈的错误信息"; break;
                case 25: result += "用户不能通信(如不在服务区、未开机等情况)"; break;
                case 26: result += "手机内存不足"; break;
                case 27: result += "手机不支持短消息"; break;
                case 28: result += "手机接收短消息出现错误"; break;
                case 29: result += "不知道的用户"; break;
                case 30: result += "不提供此功能"; break;
                case 31: result += "非法设备"; break;
                case 32: result += "系统失败"; break;
                case 33: result += "短信中心队列满"; break;

                default: result = "其它错误码" + state.ToString(); break;
            }
            return result;
        }


    }

 

    /// <summary>
    /// 计费类别定义
    /// </summary>
    public enum FeeTypes : byte
    {
        /// <summary>
        /// 0 “短消息类型”为“发送”,对“计费用户号码”不计信息费,此类话单仅用于核减SP对称的信道费
        /// </summary>
        FreeSend = 0,
        /// <summary>
        /// 1 对“计费用户号码”免费
        /// </summary>
        Free = 1,
        /// <summary>
        /// 2 对“计费用户号码”按条计信息费
        /// </summary>
        RowNumFee = 2,
        /// <summary>
        /// 3 对“计费用户号码”按包月收取信息费
        /// </summary>
        MonthFee = 3,
        /// <summary>
        /// 4 对“计费用户号码”的收费是由SP实现
        /// </summary>
        SpFee = 4,
    }
    /// <summary>
    /// Report 状态与短消息状态的映射
    /// </summary>
    public enum ReportStatus : uint
    {
        /// <summary>
        /// 0,发送成功 DELIVERED
        /// </summary>
        Delivered = 0,
        /// <summary>
        /// 1,等待发送 ENROUTE,ACCEPTED
        /// </summary>
        Accepted = 1,
        /// <summary>
        /// 2,发送失败 EXPIRED,DELETED,UNDELIVERABLE,UNKNOWN,REJECTED
        /// </summary>
        Error = 2,
    }
    public enum ErrorCodes : byte
    {

        /// <summary>
        /// 0 无错误,命令正确接收
        /// </summary>
        Success = 0,
        /// <summary>
        /// 1 非法登录,如登录名、口令出错、登录名与口令不符等。
        /// </summary>
        LoginError = 1,
        /// <summary>
        /// 2 重复登录,如在同一TCP/IP连接中连续两次以上请求登录。
        /// </summary>
        Relogon = 2,
        /// <summary>
        /// 3 连接过多,指单个节点要求同时建立的连接数过多。
        /// </summary>
        ConnectionFull = 3,
        /// <summary>
        /// 4 登录类型错,指bind命令中的logintype字段出错。
        /// </summary>
        ErrorLoginType = 4,
        /// <summary>
        /// 5 参数格式错,指命令中参数值与参数类型不符或与协议规定的范围不符。
        /// </summary>
        ParameterError = 5,
        /// <summary>
        /// 6 非法手机号码,协议中所有手机号码字段出现非86130号码或手机号码前未加“86”时都应报错。
        /// </summary>
        TelnumberError = 6,
        /// <summary>
        /// 7 消息ID错
        /// </summary>
        MsgIDError = 7,
        /// <summary>
        /// 8 信息长度错
        /// </summary>
        PackageLengthError = 8,
        /// <summary>
        /// 9 非法序列号,包括序列号重复、序列号格式错误等
        /// </summary>
        SequenceError = 9,
        /// <summary>
        /// 10 非法操作GNS
        /// </summary>
        GnsOperationError = 10,
        /// <summary>
        /// 11 节点忙,指本节点存储队列满或其他原因,暂时不能提供服务的情况
        /// </summary>
        NodeBusy = 11,
        /// <summary>
        /// 21 目的地址不可达,指路由表存在路由且消息路由正确但被路由的节点暂时不能提供服务的情况
        /// </summary>
        NodeCanNotReachable = 21,
        /// <summary>
        /// 22 路由错,指路由表存在路由但消息路由出错的情况,如转错SMG等
        /// </summary>
        RouteError = 22,
        /// <summary>
        /// 23 路由不存在,指消息路由的节点在路由表中不存在
        /// </summary>
        RoutNodeNotExisted = 23,
        /// <summary>
        /// 24 计费号码无效,鉴权不成功时反馈的错误信息
        /// </summary>
        FeeNumberError = 24,
        /// <summary>
        /// 25 用户不能通信(如不在服务区、未开机等情况)
        /// </summary>
        UserCanNotReachable = 25,
        /// <summary>
        /// 26 手机内存不足
        /// </summary>
        HandsetFull = 26,
        /// <summary>
        /// 27 手机不支持短消息
        /// </summary>
        HandsetCanNotRecvSms = 27,
        /// <summary>
        /// 28 手机接收短消息出现错误
        /// </summary>
        HandsetReturnError = 28,
        /// <summary>
        /// 29 不知道的用户
        /// </summary>
        UnknownUser = 29,
        /// <summary>
        /// 30 不提供此功能
        /// </summary>
        NoDevice = 30,
        /// <summary>
        /// 31 非法设备
        /// </summary>
        InvalidateDevice = 31,
        /// <summary>
        /// 32 系统失败
        /// </summary>
        SystemError = 32,
        /// <summary>
        /// 33 短信中心队列满
        /// </summary>
        FullSequence = 33,
        /// <summary>
        /// 未知错误
        /// </summary>
        OtherError = 99,
    }
    /// <summary>
    /// Bind操作,登录类型。
    /// </summary>
    public enum LoginTypes : byte
    {
        /// <summary>
        /// 1:SP向SMG建立的连接,用于发送命令
        /// </summary>
        SpToSmg = 1,
        /// <summary>
        /// 2:SMG向SP建立的连接,用于发送命令
        /// </summary>
        SmgToSp = 2,
        /// <summary>
        /// 3:SMG之间建立的连接,用于转发命令
        /// </summary>
        SmgToSmg = 3,
        /// <summary>
        /// 4:SMG向GNS建立的连接,用于路由表的检索和维护
        /// </summary>
        SmgToGns = 4,
        /// <summary>
        /// 5:GNS向SMG建立的连接,用于路由表的更新
        /// </summary>
        GnsToSmg = 5,
        /// <summary>
        /// 6:主备GNS之间建立的连接,用于主备路由表的一致性
        /// </summary>
        GnsToGns = 6,
        /// <summary>
        /// 11:SP与SMG以及SMG之间建立的测试连接,用于跟踪测试
        /// </summary>
        Test = 11,
        /// <summary>
        /// 其它:保留
        /// </summary>
        Unknown = 0,
    }
    /// <summary>
    /// 短消息的编码格式。
    /// </summary>
    public enum MessageCodings : byte
    {
        /// <summary>
        /// 0:纯ASCII字符串
        /// </summary>
        Ascii = 0,
        /// <summary>
        /// 3:写卡操作
        /// </summary>
        WriteCard = 3,
        /// <summary>
        /// 4:二进制编码
        /// </summary>
        Binary = 4,
        /// <summary>
        /// 8:UCS2编码
        /// </summary>
        Ucs2 = 8,
        /// <summary>
        /// 15: GBK编码
        /// </summary>
        Gbk = 15,
        /// <summary>
        /// 其它参见GSM3.38第4节:SMS Data Coding Scheme
        /// </summary>
        Others = 99,
    }
    /// <summary>
    /// 引起MT消息的原因
    /// </summary>
    public enum SubmitMorelatetoMTFlags : byte
    {
        /// <summary>
        /// 0-MO点播引起的第一条MT消息;
        /// </summary>
        VoteFirst = 0,
        /// <summary>
        /// 1-MO点播引起的非第一条MT消息;
        /// </summary>
        VoteNonFirst = 1,
        /// <summary>
        /// 2-非MO点播引起的MT消息;
        /// </summary>
        NormalFirst = 2,
        /// <summary>
        /// 3-系统反馈引起的MT消息。
        /// </summary>
        NormalNonFirst = 3,
    }
    /// <summary>
    /// Report命令类型
    /// </summary>
    public enum ReportTypes : byte
    {
        /// <summary>
        /// 0:对先前一条Submit命令的状态报告
        /// </summary>
        Submit = 0,
        /// <summary>
        /// 1:对先前一条前转Deliver命令的状态报告
        /// </summary>
        Deliver = 1,
    }
    /// <summary>
    /// 该命令所涉及的短消息的当前执行状态
    /// </summary>
    public enum ReportStates : byte
    {
        /// <summary>
        /// 0:发送成功
        /// </summary>
        Success = 0,
        /// <summary>
        /// 1:等待发送
        /// </summary>
        Accepted = 1,
        /// <summary>
        /// 2:发送失败
        /// </summary>
        Error = 2,
    }
    /// <summary>
    /// 代收费标志,0:应收;1:实收
    /// </summary>
    public enum SubmitAgentFlag : byte
    {
        /// <summary>
        /// 0:应收
        /// </summary>
        SouldIncome = 0,
        /// <summary>
        /// 1:实收
        /// </summary>
        RealIncome = 1,
    }
    /// <summary>
    /// 状态报告标记
    /// </summary>
    public enum SubmitReportFlag : byte
    {
        /// <summary>
        /// 0-该条消息只有最后出错时要返回状态报告
        /// </summary>
        ErrorReport = 0,
        /// <summary>
        /// 1-该条消息无论最后是否成功都要返回状态报告
        /// </summary>
        Always = 1,
        /// <summary>
        /// 2-该条消息不需要返回状态报告
        /// </summary>
        NoReport = 2,
        /// <summary>
        /// 3-该条消息仅携带包月计费信息,不下发给用户,要返回状态报告
        /// </summary>
        MonthReport = 3,
    }
}

 

 

 

 

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

//文件SyncEvents.cs

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

 

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

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

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

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

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

        private EventWaitHandle _newItemEvent;

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

 

 

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

//文件Util.cs

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

using System;
using System.Net.Sockets;

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

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

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

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

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


        public static uint bytes2Uint(byte[] bs, int index)
        {
            byte[] dst = new byte[4];
            Buffer.BlockCopy(bs, index, dst, 0, 4);
            byte num = dst[0];
            dst[0] = dst[3];
            dst[3] = num;
            num = dst[1];
            dst[1] = dst[2];
            dst[2] = num;
            return BitConverter.ToUInt32(dst, 0);
        }

        public static byte[] uint2Bytes(uint u)
        {
            byte[] bytes = BitConverter.GetBytes(u);
            byte num = bytes[0];
            bytes[0] = bytes[3];
            bytes[3] = num;
            num = bytes[1];
            bytes[1] = bytes[2];
            bytes[2] = num;
            return bytes;
        }
    }
}

 

 

 

 

 

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

//文件BaseSortedList.cs

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

 

using System;
using System.Collections.Generic;
using System.Reflection;


namespace AsiaINFO.SMS.SGIP
{
    public class BaseSortedList<K, V>
    {
        protected SortedList<K, V> m_List;
        protected object m_Lock;

        public BaseSortedList()
        {
            this.m_List = new SortedList<K, V>();
            this.m_Lock = new object();
        }

        public void Add(K key, V Obj)
        {
            if (!this.m_List.ContainsKey(key))
            {
                lock (this.m_Lock)
                {
                    this.m_List.Add(key, Obj);
                }
            }
        }

        public void Remove(K key)
        {
            if (this.m_List.ContainsKey(key))
            {
                lock (this.m_Lock)
                {
                    this.m_List.Remove(key);
                }
            }
        }

        public int Count
        {
            get
            {
                return this.m_List.Count;
            }
        }

        public V this[K key]
        {
            get
            {
                if (this.m_List.ContainsKey(key))
                {
                    return this.m_List[key];
                }
                return default(V);
            }
            set
            {
                lock (this.m_Lock)
                {
                    if (this.m_List.ContainsKey(key))
                    {
                        this.m_List[key] = value;
                    }
                }
            }
        }

        public SortedList<K, V> List
        {
            get
            {
                return this.m_List;
            }
        }
    }
}

 

 

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

//文件ClientQueue.cs

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

 

 

using System;
using System.Net.Sockets;

namespace AsiaINFO.SMS.SGIP
{
    public class ClientQueue
    {
        private TcpClient m_tc;
        private DateTime m_Time;

        public ClientQueue(TcpClient tc, DateTime time)
        {
            this.m_tc = tc;
            this.m_Time = time;
        }

        public TcpClient Soc
        {
            get
            {
                return this.m_tc;
            }
        }

        public DateTime Time
        {
            get
            {
                return this.m_Time;
            }
            set
            {
                this.m_Time = value;
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SGIP(Short Message Gateway Protocol)是一种通信协议,用于在电信运营商的短消息网关和短消息中心之间传递短消息。SGIP1.2是SGIP协议的一个版本,在Java语言中有相应的实现。 SGIP1.2 Java是指在Java编程语言中开发和实现SGIP1.2协议的相关功能。使用SGIP1.2 Java可以实现与电信运营商的短消息网关和短消息中心进行通信的功能,包括发送和接收短消息,查询短消息状态等。 在使用SGIP1.2 Java进行开发时,可以使用Java提供的网络编程相关的类和方法进行与短消息网关和短消息中心的连接和通信。通过建立与短消息网关和短消息中心的TCP/IP连接,可以实现双向的短消息传输。开发者可以根据SGIP1.2协议的规范,编写Java代码来解析和封装短消息的相关协议字段,实现对短消息的发送和接收。 SGIP1.2 Java的使用可以广泛应用于短信服务商、企业内部短信平台等领域,通过与电信运营商的短消息网关和短消息中心进行对接,实现短消息的批量发送和接收,并提供相关的状态查询和报告功能。同时,SGIP1.2 Java还可以结合其他相关的技术,比如数据库操作、日志记录等,提升短消息的处理效率和可靠性。 总之,SGIP1.2 Java是一种实现SGIP协议的Java编程语言版本,通过与电信运营商的短消息网关和短消息中心进行通信,实现短消息的发送、接收和状态查询等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值