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

📄 cmppspclient.cs

📁 CMPP的一个完整类
💻 CS
📖 第 1 页 / 共 5 页
字号:
//附CMPPClient.cs:
/*
作者:TNT 时间:2003年12月
文件说明:本文件实现SP端的协议开发。
*/
using System;
using System.Security.Cryptography;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections;

namespace CMPP.YOURCOMPANY
{
    public delegate void ReportEventHandler(object sender, ReportEventArgs e);  //声明一个事件的指代(指针)
    public delegate void SMSEventHandler(object sender, SMSEventArgs e);   //声明一个事件的指代(指针)
    public delegate void TerminateEventHandler(object sender, TerminateEventArgs e);   //声明收到终止信号
    public delegate void TerminateRespEventHandler(object sender, TerminateRespEventArgs e);  //回应事件发生
    public delegate void TestEventHandler(object sender, TestEventArgs e);
    public delegate void TestRespEventHandler(object sender, TestRespEventArgs e);
    public delegate void ConnectRespEventHandler(object sender, ConnectRespEventArgs e);
    public delegate void CancelRespEventHandler(object sender, CancelRespEventArgs e);
    public delegate void SubmitRespEventHandler(object sender, SubmitRespEventArgs e);
    public delegate void QueryRespEventHandler(object sender, QueryRespEventArgs e);
    public delegate void LogonSuccEventHandler(object sender, EventArgs e); //当成功登录系统
    public delegate void SocketClosedEventHandler(object sender, EventArgs e); //当套接字被检测到关闭
    public delegate void FailedItemDeletedEventHandler(object sender, WaitingQueueItemEventArgs e); //当一条等待队列的消息超过60秒没有回应


    public delegate void CMPPClientSvcStopEventHandler(object sender, ClientQueueStateArgs e); //当CMPP服务停止时候触发事件

    /// <summary>
    /// 作为CMPP协议的客户端,具有的登陆、发送、接受功能
    /// 会开3 个线程处理: 1、处理需要发送 MO(下行)的消息 
    ///       2、处理从移动服务器发送过来CMPP的消息
    ///       3、处理连接断等信息,检查需要重发的消息,检查收到的报告、短信,并调用 OnReport 事件 OnSMS事件
    /// </summary>
    public class CMPPClient
    {
        public static long CMPP_ACTIVE_TEST_C_TICKs = 30;  // *3 ;  //长连接的active_test测试时间
        public static long CMPP_ACTIVE_TEST_T_TICKs = 60;    // 消息失败时间 60秒
        public static int CMPP_ACTIVE_TEST_N_COUNT = 3;  //3次  
        //public static int CMPP_MSG_MAX=100;   //一次取得的最大消息数量
        public static int CMPP_Port = 7890;

        public event ReportEventHandler onReportHandler;   //指向事件处理代码的指针
        public event SMSEventHandler onSMSHandler;     //短信到来处理
        public event TestEventHandler onTestHandler;
        public event TestRespEventHandler onTestRespHandler;
        public event ConnectRespEventHandler onConnectRespHandler;
        public event CancelRespEventHandler onCancelRespHandler;
        public event TerminateEventHandler onTerminateHandler;
        public event TerminateRespEventHandler onTerminateRespHandler;
        public event SubmitRespEventHandler onSubmitRespHandler;
        public event QueryRespEventHandler onQueryRespHandler;
        public event LogonSuccEventHandler onLogonSuccEventHandler;
        public event SocketClosedEventHandler onSocketClosedHandler;
        public event FailedItemDeletedEventHandler onWaitingItemDeltedHandler; //当等待队列消息超时

        public event CMPPClientSvcStopEventHandler onClientSvcStopedHandler;  //当服务停止时候的事件

        //private 函数区域//////////////////////////////////////////////////////////////////////
        private Socket tcp = null;
        private IPHostEntry ip = null;
        private IPEndPoint cmpp_ep = null;
        private int RecvTimeOut = 1000;       //2000ms的接受超时
        private int SendTimeout = 2000;       //2000ms的发送超时 
        private string CMPP_Server = "";   //移动的服务器IP或者DNS名
        private string systemID = "";   //企业编号
        private string userName = "";   //sp的号码 /企业编号
        private string PassWord = "";   //口令 
        private bool isStop = false;   //本服务是否终止运行
        private bool isLogin = false;   //是否已经登录    
        private Thread Send_Thread;   //发送线程,专门处理对移动的数据包
        private Thread Recv_Thread;   //专门处理接收包
        private Thread Deamo_Thread;   //监控线程
        private string ErrorInfo = "";   //存放最后一次发生的错误信息 或者参考信息      
        private DateTime _current_time = DateTime.Now;     //上一次 ping的时间  
        private uint lastSequence;   //流水号,每一次重新启动都需要重新设定 lastSequence
        private SortedList _outSeqQueue = new SortedList();   //消息队列存储 QueueItem,存储发送队列中的状态
        private SortedList _waitingSeqQueue = new SortedList(); //消息队列存储 QueueItem
        private int sub_resp = 0;       //最后返回的包 Sequence
        private DateTime _lastOkTime;      //最后正确发送消息时间
        private bool _bNre = false;      //空引用错误,套接字错误

        //private ManualResetEvent _connectionDone=new ManualResetEvent(false); //是否连接到套接字服务器,也就是CMPP服务器
        //private ManualResetEvent _lastsendDone=new ManualResetEvent(false);  //上一次发送是否完毕
        //private ManualResetEvent _lastrecvDone=new ManualResetEvent(false);  //上一次接收是否完毕

        private void ping()    //发送一次ping包 ,不经过_outSeqQueue 直接存储在 out queue中
        {
            uint seq = this.getNextSequence();
            MSG.CMPP_MSG_TEST test = new MSG.CMPP_MSG_TEST(seq);
            QueueItem q = new QueueItem(seq, (uint) MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST, 0, 0);
            q.setmsgObj(test);
            this.addToOutQueue(q);
        }

        private string getValIdTime(DateTime d)        //返回短信存活时间
        {
            DateTime n = d.AddHours(2); //2小时
            return (n.Year.ToString().Substring(2) + n.Month.ToString().PadLeft(2, '0') + n.Day.ToString().PadLeft(2, '0') + n.Hour.ToString().PadLeft(2, '0') + n.Minute.ToString().PadLeft(2, '0') + n.Second.ToString().PadLeft(2, '0') + "032+");
        }

        private bool isPingTime()  //是否到了ping一次的时间
        {
            System.TimeSpan l = (DateTime.Now - this._current_time);

            if (l.TotalSeconds >= (CMPPClient.CMPP_ACTIVE_TEST_C_TICKs))
            {
                lock (this)
                {
                    this._current_time = DateTime.Now;
                    return (true);
                }
            }
            else
            {
                return (false);
            }
        }

        private void checkReSend()    //是否需要再一次ping //查询 _waitingSeqQueue 是否存在 上一次 没有相应的消息
        {   //调查waiting queue 中的所有消息,如果入列时间超过60 
            for (int i = 0; i < this._waitingSeqQueue.Count; i++)
            {
                Thread.Sleep(20);
                QueueItem q = (QueueItem) this._waitingSeqQueue.GetByIndex(i);
                if (q != null)
                {
                    DateTime this_time = DateTime.Now; //去当前时间
                    TimeSpan t = this_time - q.inQueueTime;
                    if (t.TotalSeconds > CMPPClient.CMPP_ACTIVE_TEST_T_TICKs) //达到超时时间
                    {//需要重新发送消息
                        if (q.FailedCount >= CMPPClient.CMPP_ACTIVE_TEST_N_COUNT)
                        {
                            //报告消息发送失败
                            if (this.onWaitingItemDeltedHandler != null)
                            {
                                WaitingQueueItemEventArgs e = new WaitingQueueItemEventArgs(q);
                                this.onWaitingItemDeltedHandler(this, e);
                            }
                            this.delFromWaitingQueue(q); //从等待队列中删除 
                            //q.MsgState =(int)MSG_STATE.SENDED_WAITTING; 
                        }
                        else
                        {//可以尝试继续发送
                            q.inQueueTime = this_time;
                            q.FailedCount++;
                            q.MsgState = (int) MSG_STATE.SENDED_WAITTING;
                            this.sendQueueItem(q);
                        }
                    }
                }
            }

        }

        private void startThreads()
        {
            Deamo_Thread = new Thread(new ThreadStart(this.DeamonThread));
            Deamo_Thread.Start();
        }

        private QueueItem newQueueItem(int msgtype, int msgstate, object msg)  //生成一个消息队列成员对象实例
        {
            uint seq = this.getNextSequence();   // 
            QueueItem q = new QueueItem(seq, (uint) msgtype, 0, msgstate);
            q.setmsgObj(msg);       //设定消息为 object
            return (q);
        }

        private QueueItem getOutQueueItem(uint seq)  //获取MT 队列中的消息项目
        {
            lock (this)
            {
                return ((QueueItem) this._outSeqQueue[seq]);
            }
        }

        private QueueItem getWaitingQueueItem(uint seq)  //获取等待队列中的消息
        {
            return ((QueueItem) this._waitingSeqQueue[seq]);
        }

        private void addToOutQueue(QueueItem q)
        {
            lock (this)
            {
                this._outSeqQueue.Add(q.Sequence, q);
            }
        }

        private void addToWaitingQueue(QueueItem q)
        {
            lock (this)
            {
                if (!this._waitingSeqQueue.ContainsKey(q.Sequence))
                {
                    this._waitingSeqQueue.Add(q.Sequence, q);
                }
            }
        }

        private QueueItem getTopOutQueue()     //需要在取之前进行判断
        {
            for (int i = 0; i < this._outSeqQueue.Count; i++)
            {
                QueueItem q = (QueueItem) this._outSeqQueue.GetByIndex(i);
                if (q != null)
                {
                    if (q.MsgState == (int) MSG_STATE.NEW)  //新消息,立即返回
                    {
                        lock (this)
                        {
                            q.MsgState = (int) MSG_STATE.SENDING; //发送状态 
                        }
                        return (q);
                    }
                    else
                    {
                        q = null;
                    }
                }
            }
            return (null);
        }

        private ArrayList getTop16Queue() //返回16条最顶的消息
        {
            int arrlength = 0;
            ArrayList reArr = new ArrayList();
            QueueItem q = getTopOutQueue();
            while (q != null || arrlength <= 16)
            {
                if (q != null)
                {
                    reArr.Add(q);
                    arrlength++;
                }
                else
                {
                    break;
                }
                q = getTopOutQueue();
            }

            if (arrlength > 0)
            {
                return (reArr);
            }
            else
            {
                return (null);
            }
        }

        private void delFromOutQueue(QueueItem q)
        {
            lock (this)
            {
                this._outSeqQueue.Remove(q.Sequence);
            }
        }

        private void delFromOutQueue(uint seq)
        {
            lock (this)
            {
                this._outSeqQueue.Remove(seq);
            }
        }

        private void delFromWaitingQueue(QueueItem q)
        {
            lock (this)
            {
                this._waitingSeqQueue.Remove(q.Sequence);
            }
        }

        private void delFromWaitingQueue(uint seq)
        {
            this._waitingSeqQueue.Remove(seq);
        }

        private void SendLogin(string SystemID, string spNum, string Password)
        {//发送登录验证包    
            systemID = SystemID;
            userName = spNum;
            PassWord = Password;
            uint seq = this.getNextSequence(); //取得一个流水号 
            MSG.CMPP_MSG_CONNECT cn = new MSG.CMPP_MSG_CONNECT(seq);
            cn.Password = Password.Trim();
            cn.SourceAdd = SystemID.Trim();
            tcp.Send(cn.ToBytes());
        }


        private byte[] prepairPKs(QueueItem outitem)//将QueueItem发送出去
        {
            uint seq = outitem.Sequence;
            uint msgtype = outitem.MsgType;

⌨️ 快捷键说明

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