shanhe YID:shanhe
268275次访问,排名203好友0人,关注者8
互联网老兵
shanhe的文章
原创 142 篇
翻译 0 篇
转载 0 篇
评论 204 篇
shanhe的公告
最近评论
hdnero:wow power leveling
hdnero:wow power leveling
hdnero:wow power leveling
hdnero:wow power leveling
zwf0713:good job!
文章分类
收藏
    相册
    daughter
    prog
    .NET
    在没有 IIS 的条件下运行 ASMX
    IT
    为BT平反:被指传播间谍软件可能是场阴谋
    将消逝的十大热门技术
    web
    社会文化
    七大阻碍中国文明发展的事件
    超级女声:数千万人对数千万人的民意决选
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 CMPP SP端 C# 实例收藏

    新一篇: ASP.NET组件设计Step by Step | 旧一篇: 动态发布站点的并发访问升级简易方案

    //附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;  
       switch(msgtype)
       {
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST :
         MSG.CMPP_MSG_TEST test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
         }
         outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
         return(test.toBytes());      
          
     
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP:
         MSG.CMPP_MSG_TEST_RESP test_reply=(MSG.CMPP_MSG_TEST_RESP)outitem.getMsgObj(); //发送队列中取出//取出需要发送的具体消息
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
         }
         outitem.MsgState = (int)MSG_STATE.SENDING_FINISHED ;  //完成
         return(test_reply.toBytes());
          
          
     
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL :
         MSG.CMPP_MSG_CANCEL cancel=(MSG.CMPP_MSG_CANCEL)outitem.getMsgObj();    //还原成消息类
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue(outitem);    //等待回应
         }
         outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
         return(cancel.toBytes());     
     
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER_RESP:
         MSG.CMPP_MSG_DELIVER_RESP deliver_resp=(MSG.CMPP_MSG_DELIVER_RESP)outitem.getMsgObj(); //发送队列中取出;
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
         }
         outitem.MsgState=(int)MSG_STATE.SENDING_FINISHED  ;  //完成
         return (deliver_resp.toBytes());      
          
     
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY  :
         MSG.CMPP_MSG_QUERY query = (MSG.CMPP_MSG_QUERY )outitem.getMsgObj(); //发送队列中取出;
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING  ;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue(outitem);
         }
         outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ; //等待回应
         return(query.toBytes());      
          
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT :
         MSG.CMPP_MSG_SUBMIT submit =(MSG.CMPP_MSG_SUBMIT)outitem.getMsgObj(); //发送队列中取出;
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue (outitem);
         }
         outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED ;
         return(submit.toBytes());
                
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
         MSG.CMPP_MSG_TERMINATE terminate=(MSG.CMPP_MSG_TERMINATE)outitem.getMsgObj(); //发送队列中取出;
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue(outitem);
         }
         outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
         return(terminate.toBytes());     
     
        case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
         MSG.CMPP_MSG_TERMINATE_RESP terminate_resp=(MSG.CMPP_MSG_TERMINATE_RESP)outitem.getMsgObj(); //发送队列中取出;
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING ;
          this.delFromOutQueue(seq);
         }
         outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED  ;
         return(terminate_resp.toBytes()); 

        default:  
         test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
         lock(this)
         {
          outitem.MsgState =(int)MSG_STATE.SENDING;
          this.delFromOutQueue(seq);
          this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
         }
         outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
         return(test.toBytes()); 
       }   
      }

      private void sendQueueItem(QueueItem outitem)//将QueueItem发送出去
      {
       uint seq=outitem.Sequence ;
       uint msgtype=outitem.MsgType;
       try
       {
        switch(msgtype)
        {
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST :
          MSG.CMPP_MSG_TEST test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING;
           this.delFromOutQueue(seq);
           this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
          }
          tcp.Send(test.toBytes());
          outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP:
          MSG.CMPP_MSG_TEST_RESP test_reply=(MSG.CMPP_MSG_TEST_RESP)outitem.getMsgObj(); //发送队列中取出//取出需要发送的具体消息
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);
          }
          tcp.Send(test_reply.toBytes());
          outitem.MsgState = (int)MSG_STATE.SENDING_FINISHED ;  //完成
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL :
          MSG.CMPP_MSG_CANCEL cancel=(MSG.CMPP_MSG_CANCEL)outitem.getMsgObj();    //还原成消息类
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);
           this.addToWaitingQueue(outitem);    //等待回应
          }
          tcp.Send(cancel.toBytes());     
          outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER_RESP:
          MSG.CMPP_MSG_DELIVER_RESP deliver_resp=(MSG.CMPP_MSG_DELIVER_RESP)outitem.getMsgObj(); //发送队列中取出;
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);
          }
          tcp.Send(deliver_resp.toBytes());
          outitem.MsgState=(int)MSG_STATE.SENDING_FINISHED  ;  //完成
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY  :
          MSG.CMPP_MSG_QUERY query = (MSG.CMPP_MSG_QUERY )outitem.getMsgObj(); //发送队列中取出;
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING  ;
           this.delFromOutQueue(seq);
           this.addToWaitingQueue(outitem);
          }
          tcp.Send(query.toBytes());
          outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ; //等待回应
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT :
          MSG.CMPP_MSG_SUBMIT submit =(MSG.CMPP_MSG_SUBMIT)outitem.getMsgObj(); //发送队列中取出;
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);
           this.addToWaitingQueue (outitem);
          }
          tcp.Send(submit.toBytes());
          outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED ;
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
          MSG.CMPP_MSG_TERMINATE terminate=(MSG.CMPP_MSG_TERMINATE)outitem.getMsgObj(); //发送队列中取出;
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);
           this.addToWaitingQueue(outitem);
          }
          if(this.tcpIsCanUse())
          {
           tcp.Send(terminate.toBytes());
           outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;       
          }
          this.isStop =true;     //通知其他线程可以退出了
          break;
     
         case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
          MSG.CMPP_MSG_TERMINATE_RESP terminate_resp=(MSG.CMPP_MSG_TERMINATE_RESP)outitem.getMsgObj(); //发送队列中取出;
          lock(this)
          {
           outitem.MsgState =(int)MSG_STATE.SENDING ;
           this.delFromOutQueue(seq);       
          }
          tcp.Send(terminate_resp.toBytes());
          outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED  ;     
          break;
        }
        LogLastOkTime(DateTime.Now );  //记录当前最后一次消息soket正确时间
       }
       catch(SocketException se)
       {
        //发生套接字错误
        this.ErrorInfo =this.ErrorInfo +"\r\n"+se.ToString ();
       }
       catch(NullReferenceException nre)
       {
        this._bNre =true;  //出现空引用错误
        this.ErrorInfo =this.ErrorInfo +"\r\n"+nre.ToString ();
       }
      }
     
      private bool tcpIsCanUse()  //测试当前tcp是否可用
      {
       bool reval=true;
       DateTime t=DateTime.Now ;
       TimeSpan ts=t- this._lastOkTime;
       if(ts.TotalSeconds > CMPPClient.CMPP_ACTIVE_TEST_T_TICKs ) //60秒
       {
        reval=false;  //不可用
       }
       if(this._bNre )
       {
        reval=false;
       }
       return(reval);
      }
     
      private void _reStartRecvNSend()
      {
       Send_Thread=new Thread(new ThreadStart(this.SendSPMsgThread));
       Send_Thread.Start();
       Recv_Thread=new Thread(new ThreadStart(this.RecvISMGMsgThread));
       Recv_Thread.Start();
      }
     
      private void LogLastOkTime(DateTime lastoktime)
      {
       lock(this)
       {
        this._lastOkTime=lastoktime;  //设定最后成功消息交互时间
       }
      }
     
      private void defaultReportHandler() //却省的报告事件处理函数
      {
     
      }
     
      private void defaultSMSHandler()
      {
     
      }
     
      private void defaultTeminateHandler()
      {
     
      }
     
      private void defaultTestEventHandler()
      {
     
      }
      private void defaultTestRespEventHandler()
      {
     
      }
      private void defaultTerminateEventHandler()
      {
      }
      private void defaultTerminateRespEventHandler()
      {
      }
      private void defaultCancelRespEventHandler()
      {
      }
      private void defaultQueryRespEventHandler()
      {
      }
     
      private void defaultConnectRespEventHandler()
      {
       QueueItem q=new QueueItem(this.getNextSequence(),(uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST,0,(int)MSG_STATE.NEW);
       MSG.CMPP_MSG_TEST test=new MSG.CMPP_MSG_TEST(q.Sequence ); //立即发送包过去
       q.setmsgObj(test);
       this.addToOutQueue(q);  
      }
      private void defaultSubmitRespEventHandler()
      {
      }

      private void defaultClientStopEventHandler()
      {}
        
      private void rePortError(string info)
      {
     
      }
           
      private bool _init(string CMPPServer,int CMPPPort)
      {
       bool reVal=false;
       CMPP_Server=CMPPServer;
       CMPP_Port=CMPPPort;
       try
       {
        tcp=new Socket(AddressFamily.InterNetwork ,SocketType.Stream ,ProtocolType.Tcp );
        ip=Dns.GetHostByName(CMPP_Server);
        cmpp_ep=new IPEndPoint(ip.AddressList[0],CMPP_Port);
        tcp.Connect(cmpp_ep); //连接
        reVal=true;  
       }
       catch(SocketException se)
       {
        ErrorInfo="Socker Error:" + se.ToString();
       }
       return(reVal);  
      }
      private uint getNextSequence()
      {
       lock(typeof(CMPPClient))
       {
        try
        {
         lastSequence++;
        }
        catch(OverflowException ofe)
        {
         this.ErrorInfo =this.ErrorInfo +"\r\n"+ofe.ToString();
         lastSequence=uint.MinValue;
        }       
        return(lastSequence);
       }
      }
     
      private void RecvISMGMsgThread()   //处理ISMG消息的线程
      {
       while(!this.isStop )
       {
        try
        {    
         byte[] rbuf=new byte[10240]; //结果缓冲区
         byte[] recv_temp=new Byte[1024]; //recv临时缓冲区
         int index=0;
         int msglength=tcp.Receive(rbuf);  //阻塞接收//分析收到的数据
     
         MSG.CMPP_MSG_Header header;  //=new MSG.CMPP_MSG_Header(rbuf,index); //取得一个消息                   
         while(index<msglength) //逐个消息分析
         {
          header=new MSG.CMPP_MSG_Header(rbuf,index); //取得一个消息      
          byte[] the_pk= new byte[header.MSGLength] ;   //生成此消息的大小
          for(int i=0;i<header.MSGLength ;i++)
          {
           the_pk[i]=rbuf[index++];
          }      
          uint seq; //取得回复消息的下一个流水序列号
          switch(header.Command_ID)
          {
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST : //服务器给客户的测试信号
            this.ErrorInfo =this.ErrorInfo +"\r\n"+"收到:CMPP_ACTIVE_TEST";
            MSG.CMPP_MSG_TEST test=new MSG.CMPP_MSG_TEST(the_pk);
            seq=test.Sequence;       //取得发送过来的流水号
            MSG.CMPP_MSG_TEST_RESP test_reply=new MSG.CMPP_MSG_TEST_RESP(seq);  
            tcp.Send(test_reply.toBytes());    //马上送出回应包,不需要进入队列 
            if(this.onTestHandler!=null)
            {
             TestEventArgs e=new TestEventArgs(test);
             onTestHandler(this,e);
            }
            else
            {
             defaultTestEventHandler();
            }
            this.ErrorInfo =this.ErrorInfo +"\r\n"+"发送:CMPP_ACTIVE_TEST_RESP ";
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP : //服务器的回应消息,应当丢弃不管
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_ACTIVE_TEST_RESP ");
            MSG.CMPP_MSG_TEST_RESP test_reply2=new MSG.CMPP_MSG_TEST_RESP(the_pk); //构造消息
            seq=test_reply2.Sequence;    //寻找 曾经发送过去的消息        
            this.delFromWaitingQueue(seq);      //删除等待队列中的消息 //清空等待回应队列
            if(this.onTestRespHandler!=null)
            {
             TestRespEventArgs e=new TestRespEventArgs(test_reply2);
             onTestRespHandler(this,e);
            }
            else
            {
             defaultTestRespEventHandler();
            }
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL_RESP :
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_CANCEL_RESP ");
            MSG.CMPP_MSG_CANCEL_RESP cancel_reply=new MSG.CMPP_MSG_CANCEL_RESP(the_pk);//构造消息
            seq=cancel_reply.Sequence;
            this.delFromWaitingQueue(seq);
            if(this.onCancelRespHandler!=null)
            {
             CancelRespEventArgs e=new CancelRespEventArgs(cancel_reply);
             onCancelRespHandler(this,e);
            }
            else
            {
             defaultCancelRespEventHandler();
            }
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_CONNECT_RESP :   //检查下消息的正确性,清除等待队列 设定连接成功标志
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_CONNECT_RESP ");
            MSG.CMPP_MSG_CONNECT_RESP cn_reply=new MSG.CMPP_MSG_CONNECT_RESP(the_pk);
            seq=cn_reply.Sequence;     //取得消息的seq
            if(this.onConnectRespHandler !=null)
            {
             ConnectRespEventArgs e=new ConnectRespEventArgs(cn_reply);
             onConnectRespHandler(this,e);
            }
            else
            {
             defaultConnectRespEventHandler();
            }
            if(cn_reply.isOk)
            {
             this.isLogin  =true;
            }
            else
            {
             this.isLogin  =false;
            }
            this.delFromWaitingQueue(seq);    //删除队列中的等待连接信息包
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER:    //检查消息正确定,立即返回 正确 或者 失败,正确则处理是否状态包,不是状态包则存到MO缓存,表示收到信息,时状态包则判断缓存消息进行消息送达处理
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_DELIVER ");
            BIConvert.DumpBytes(the_pk,"c:\\CMPP_DELIVER.txt");//保留映像
            MSG.CMPP_MSG_DELIVER deliver=new MSG.CMPP_MSG_DELIVER(the_pk);       
            seq=(uint)deliver.ISMGSequence;       //发过来的流水号,需要立即发送一个deliver_resp       //一条 ISMG--〉SP 的消息
            MSG.CMPP_MSG_DELIVER_RESP deliver_resp=new MSG.CMPP_MSG_DELIVER_RESP(seq);      
            deliver_resp.MsgID =deliver.MsgID ;
            deliver_resp.Result =0;
            byte[] t=deliver_resp.toBytes();
            tcp.Send(t);
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("发送:CMPP__DELIVER_RESP ");
            if(deliver.isReport)
            {      //删除等待队列的消息//报告消息已经正确发送到        
             //UInt64 ReportMsgID=deliver.ReportMsgID ; //取得消息ID ,更新 MsgID
             string StateReport=deliver.StateReport; //取得关于此消息的状态
             //_debugBs(the_pk);
             ReportEventArgs arg=new ReportEventArgs(the_pk,MSG.CMPP_MSG_Header.HeaderLength+8+21+10+1+1+1+21+1+1);    //构造报告事件参数
             //ReportEventArgs arg=new ReportEventArgs(ReportMsgID.ToString(),
             if(this.onReportHandler!=null) //ReportEventArgs传递的字节数组是 报告信息包的数据,在此不考虑多个报告的情况
             {
              onReportHandler(this,arg);
             }
             else
             {
              this.defaultReportHandler(); 
             }
            }
            else
            {//SMSEventArgs 传递的整个deliver包
             SMSEventArgs smsarg=new SMSEventArgs (the_pk,MSG.CMPP_MSG_Header.HeaderLength); 
             if(this.onSMSHandler!=null)
             {
              onSMSHandler(this,smsarg);   //触发事件,应当很快结束处理,不要靠考虑存储之类的耗费资源事宜
             }
             else
             {
              defaultSMSHandler();
             }
            }   
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY_RESP :
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_QUERY_RESP ");
            //收到消息,处理后存入数据库
            MSG.CMPP_MSG_QUERY_RESP query_resp=new MSG.CMPP_MSG_QUERY_RESP(the_pk);
            this.delFromWaitingQueue(query_resp.Sequence );   //将等待的队列中的元素删除
            if(this.onQueryRespHandler!=null)
            {
             QueryRespEventArgs e=new QueryRespEventArgs(query_resp);
            }
            else
            {
             defaultQueryRespEventHandler();
            }
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT_RESP :    //收到服务器送达的慧英消息
            this.ErrorInfo =this.ErrorInfo +"\r\n"+("收到:CMPP_SUBMIT_RESP ");        
            MSG.CMPP_MSG_SUBMIT_RESP submit_resp=new MSG.CMPP_MSG_SUBMIT_RESP(the_pk); 
            BIConvert.DumpBytes(the_pk,"c:\\CMPP_SUBMIT_RESP.txt");//保留映像
            //BIConvert.DumpBytes(initValue,"c:\\CMPP_SUBMIT_RESP.txt");//保留映像
            sub_resp++; //该变量仅供测试使用
            delFromWaitingQueue(submit_resp.Sequence);  //删除需要等待的消息
            if(this.onSubmitRespHandler!=null)
            {
             SubmitRespEventArgs e=new SubmitRespEventArgs(submit_resp);
             //submit_resp.
             onSubmitRespHandler(this,e);
            }
            else
            {
             defaultSubmitRespEventHandler();
            }
     
            break;
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
            this.ErrorInfo =this.ErrorInfo +"\r\n"+"收到:CMPP_TERMINATE";
            MSG.CMPP_MSG_TERMINATE terminate=new MSG.CMPP_MSG_TERMINATE(the_pk);
            seq=terminate.Sequence;
            MSG.CMPP_MSG_TERMINATE_RESP  terminate_resp=new MSG.CMPP_MSG_TERMINATE_RESP(seq);
            this.ErrorInfo =this.ErrorInfo +"\r\n"+"收到:CMPP_TERMINATE_RESP";
            tcp.Send(terminate_resp.toBytes()); 
            if(this.onTerminateHandler!=null)
            {
             TerminateEventArgs e=new TerminateEventArgs(terminate);
             onTerminateHandler(this,e);
             this.StopMe() ; //准备自我停止?
            }
            else
            {
             defaultTerminateEventHandler();
            }
            this._StopMe();  //发出终止设定        
            return;   //退出线程        
     
           case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
            this.ErrorInfo =this.ErrorInfo +"\r\n"+"收到:CMPP_TERMINATE_RESP";
            MSG.CMPP_MSG_TERMINATE_RESP ter_resp=new MSG.CMPP_MSG_TERMINATE_RESP(the_pk);
            seq=ter_resp.Sequence ;  //取得流水信号
            this.delFromOutQueue(seq);   //删除输出表重点项目
            if(this.onTerminateRespHandler!=null)
            {
             TerminateRespEventArgs e=new TerminateRespEventArgs(ter_resp);
             onTerminateRespHandler(this,e);
            }
            else
            {
             defaultTerminateRespEventHandler();
            }
            this._StopMe();
            break;
          }            
         }     
         LogLastOkTime(DateTime.Now );  //记录当前最后一次消息soket正确时间
        }
        catch(SocketException se)
        {
         //超时   
        }
        Thread.Sleep(50);
       }  
      }
      //debug
    //  private void _debugBs(byte[] the_pk) //存储byte字节
    //  {
    //   
    //  }
      //debug
     
      private void DeamonThread()    //监视本系统连接是否正常
      {//此线程是监视线程
       int  t_count =0;   //循环时间计数
       _reStartRecvNSend();   //启动接收和发送
       while(! this.isStop)
       {      
        t_count++;    //0.1秒   
        if(tcpIsCanUse()) 
        {
         if(this.isPingTime())
         {
          this.ping();  //发送一个ping包
         }
         if(t_count>50)  // 500*100=50000=50秒
         {
          t_count=0;
          checkReSend() ; //检查需要重新发送的消息
          //触发一个事件,让系统自动检查消息队列,存储消息队列中的消息状态
         }
        }
        else
        {
         EventArgs e=new EventArgs();
         if(this.onSocketClosedHandler!=null)
         {
          onSocketClosedHandler(this,e);
         }
         else
         {     
         }
         this.isStop =true;  //通知其他线程退出
        }
        Thread.Sleep(1000);
       }
      }  
     
      private void SendSPMsgThread()
      {
       while (!this.isStop )
       {
        Thread.Sleep(10);
        if(this.isLogin)
        {
         ArrayList lists=this.getTop16Queue();  //取出16条最顶的消息    
         if(lists!=null  && lists.Count >0)
         {
          int count=lists.Count;            
          ArrayList pks=new ArrayList( count); //定义容量
          for (int i=0;i<lists.Count; i++)
          {
           QueueItem outitem=(QueueItem)lists[i]; //取出每一个消息对象
           if(outitem!=null)
           {
            try
            {
             sendQueueItem(outitem);    //发送每一个消息
            }
            catch(SocketException se)
            {
             //发送失败
             outitem.FailedCount ++;
            }
           }      
          }
         }
        }
        Thread.Sleep(100);
       }  
      } 

      private void _StopMe()
      {
       lock(this)
       {
        this.isStop =true;
       }
      }
     
      private void _forcedSubThread(Thread t)   //强制停止线程
      {
       try
       {
        t.Abort();
        t.Join(); 
       }
       catch(Exception )
       {}
      }
     
      //private 函数区域//////////////////////////////////////////////////////////////////
     
     
      //公用函数 属性区域////////////////////////////////////////
      public bool Init(string CMPPServer,int CMPPPort)
      {
       return(this._init(CMPPServer,CMPPPort));
      }
     
      public bool Init(string CMPPServer,int CMPPPort,int recvtimeout,int sendtimeout)
      {
       this.RecvTimeOut =recvtimeout;
       this.SendTimeout =sendtimeout;
       return(this._init(CMPPServer,CMPPPort));
      }
     
      public bool Init(string CMPPServer,int CMPPPort,int recvtimeout)
      {
       this.RecvTimeOut =recvtimeout;
       this.SendTimeout =recvtimeout;
       return(this._init(CMPPServer,CMPPPort));
      }
      
      public bool Login(string SystemID,string UserName,string Password)
      {
       try
       {
        SendLogin(SystemID, UserName, Password);
        this.LogLastOkTime(DateTime.Now);    //最后一次正确的发送
       }
       catch(SocketException se)
       {
        //发送出错
        this.ErrorInfo = this.ErrorInfo +"\r\n"+se.ToString();
        return(false);
       }
       DateTime t1=DateTime.Now;
       while(!this.isLogin)
       {
        byte[] rbuf=new Byte[400];
        int l;
        try
        {
         l=tcp.Receive(rbuf) ;
         if(l>16)
         {
          if(BIConvert.Bytes2UInt(rbuf,4)==(uint)MSG.CMPP_COMMAND_ID.CMPP_CONNECT_RESP)
          {
           MSG.CMPP_MSG_CONNECT_RESP resp=new MSG.CMPP_MSG_CONNECT_RESP(rbuf);
           if(resp.isOk)
           {
            EventArgs e=new EventArgs();
            if(onLogonSuccEventHandler!=null)
            {
             onLogonSuccEventHandler(this,e);
            }
            else
            {
             this.defaultConnectRespEventHandler();
            }
            this.isLogin =true;
           }
           else
           {
           }
           break;
          }
         }
         this._lastOkTime =DateTime.Now ;  //更新当前最后成功收发套接字的时间
        }
        catch(SocketException)
        {
        }
        System.TimeSpan t=DateTime.Now - t1;
        if(t.TotalSeconds > 10)
        {
         break;
        }
       }  
       if(this.isLogin)
       { //登录ok,就立即发送active_test包
        this.ErrorInfo =this.ErrorInfo + "\r\n"+" Logon succ! ";    
        startThreads();  // 启动 主监视程序de线程
        return(true);
       }
       else
       {
        return(false);
       }
      }
       
      public uint SubmitSMS(string to_user,string fee_code,string svc_code, string fee_user,string spnum,string content,int fee_usertype)
      {
       MSG.CMPP_MSG_SUBMIT sndmsg; 
       uint seq=this.getNextSequence();   //取得下一个sequence
       sndmsg=new MSG.CMPP_MSG_SUBMIT(seq);
       sndmsg.FeeCode =fee_code;
       sndmsg.FeeTerminalId =to_user;
       sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM; //按条收取
       sndmsg.FeeUserType = fee_usertype ;
       sndmsg.Msg_Level=0;
       sndmsg.MSGFormat = (uint)MSG.Msg_Format.UCS2;
       sndmsg.SMS_Content=content;
       sndmsg.SrcID=spnum;         //长号码
       sndmsg.SPID=this.systemID ;
       sndmsg.Svc_Code= svc_code;
       sndmsg.UDHI=0;
       sndmsg.ValIdTime=getValIdTime(DateTime.Now);        //存活时间
       sndmsg.addTerminalID(to_user);
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT  ,0,0); 
       q.setmsgObj(sndmsg);
       this.addToOutQueue(q);  
       return(seq);
      }
     
      public uint SendMsg(string to_user,string fee_user,string fee,string svccode,string content,string spnum)
      {
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
       sndmsg.FeeCode=fee;
       sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM ;
       sndmsg.FeeTerminalId =fee_user;
       sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_NULL ;    //计费 按照计费号码计费
       sndmsg.SPID =this.systemID ;         //企业代码
       sndmsg.UDHI=0;             //
       sndmsg.MSGFormat=(uint)MSG.Msg_Format.GB2312 ;
       sndmsg.SMS_Content =content;
       sndmsg.SrcID=spnum;
       sndmsg.Svc_Code=svccode;
       sndmsg.addTerminalID(to_user);
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT  ,0,0); 
       q.setmsgObj(sndmsg);
       this.addToOutQueue(q);
       return(seq);
      }
     
      public uint SendSMC(string fee_user,string feecode,string svccode)  //向计费用户发送一条包月计费信息
      {
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
       sndmsg.SMS_Delivery_Type=2;         //产生包月SMC
       sndmsg.FeeCode=feecode;
       sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_MONTH ;   //包月计费
       sndmsg.FeeTerminalId =fee_user;
       sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_TERMINAL_ID  ;    //计费 按照计费号码计费
       sndmsg.SPID =this.systemID ;         //企业代码
       sndmsg.UDHI=0;             //
       sndmsg.MSGFormat=(uint)MSG.Msg_Format.UCS2 ;
       sndmsg.SMS_Content ="SMC";  
       sndmsg.SrcID =this.userName;         //sp的特符号码
       sndmsg.Svc_Code=svccode;
       sndmsg.addTerminalID(fee_user);
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT ,0,0); 
       q.setmsgObj(sndmsg);
       this.addToOutQueue(q);
       return(seq);
      }
     
      public uint SendSMT(string to_user,string feecode,string svccode,string spnum,string content)
      {
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
       sndmsg.SMS_Delivery_Type=1;         //产生包月SMC
       sndmsg.FeeCode=feecode;          //包月计费代码
       sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_MONTH ;   //包月计费
       sndmsg.FeeTerminalId =to_user;
       sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_TERMINAL_ID  ;    //计费 按照计费号码计费
       sndmsg.SPID =this.systemID ;         //企业代码
       sndmsg.UDHI=0;             //
       sndmsg.MSGFormat=(uint)MSG.Msg_Format.UCS2 ;
       sndmsg.SMS_Content =content;
       sndmsg.SrcID =spnum;         //sp的特符号码
       sndmsg.Svc_Code=svccode;
       sndmsg.addTerminalID(to_user);
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT ,0,0); 
       q.setmsgObj(sndmsg);
       this.addToOutQueue(q);
       return(seq);
      }
      
      public uint SendQuery(string svccode,string whichday) //查询某个业务的总计数
      {
       string wd=whichday.Trim();
       int query_type=0;
       if(svccode==null || svccode.CompareTo("")==0)
       {//查询全部页数量
       }
       else
       {//查询某项业务
        query_type=1;
       }
       if(wd==null|| wd.CompareTo ("")==0)
       {
        DateTime d=DateTime.Now;
        wd=d.Year.ToString()+d.Month.ToString().PadLeft(2,'0')+d.Day.ToString().PadLeft(2,'0');       
       }
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_QUERY query=new MSG.CMPP_MSG_QUERY(seq); 
       query.Query_Type =query_type;
       query.Query_Code =svccode;
       query.Time =wd;     //设定那一天
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY ,0,0); 
       q.setmsgObj(query);
       this.addToOutQueue(q);
       return(seq);   //返回消息的内部编号
      }
     
      public uint StopCMPPConnection()   //停止CMPP协议的socket连接
      {
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_TERMINATE t=new MSG.CMPP_MSG_TERMINATE(seq);
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE,0,0);
       q.setmsgObj(t);
       this.addToOutQueue(q);
       return(seq); //返回终止消息,便于等待
      }
     

      public uint CancelMsg( string   msgid)
      {
       uint seq=this.getNextSequence();
       MSG.CMPP_MSG_CANCEL  cancel=new MSG.CMPP_MSG_CANCEL(seq); 
       cancel.MsgID =msgid;
       QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL  ,0,0); 
       q.setmsgObj(cancel);
       this.addToOutQueue(q);
       return(seq);   //返回消息的内部编号
      }
     
      public void StopMe()
      {
       if(!this.isStop)
       {
        if(this.tcpIsCanUse())//发送一条对服务器的通告
        {
         uint seq=this.getNextSequence();
         MSG.CMPP_MSG_TERMINATE t=new MSG.CMPP_MSG_TERMINATE(seq);
         QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE,0,0);
         q.setmsgObj(t);
         this.addToOutQueue(q);
        }  
        Thread.Sleep(500);   //等待1000ms,告知服务器
        this._StopMe();
        tcp.Close();

        if(this.onClientSvcStopedHandler!=null)
        {
         ClientQueueStateArgs  arg=new ClientQueueStateArgs(this._outSeqQueue ,this._waitingSeqQueue);
         onClientSvcStopedHandler(this,arg);
        }
        else
        {
         this.defaultClientStopEventHandler();
        }
        Thread.Sleep(500);   //再次主动等待线程结束         
        //此处报告 2个队列中的信息    
       }
       //准备强行结束
       _forcedSubThread(this.Send_Thread);
       Thread.Sleep(500);   //等待1000ms,告知服务器
       _forcedSubThread(this.Recv_Thread );
       Thread.Sleep(500);   //等待1000ms,告知服务器
       _forcedSubThread(this.Deamo_Thread );  
       Thread.Sleep(500);   //等待1000ms,告知服务器
      }
     
      public string getLogInfo()
      {
       string t= this.ErrorInfo;
       this.ErrorInfo="";
       return(t);  
      }

      public int getQueueItemState(uint seq)  //根据seq寻找发送内部队列的消息对象的状态
      {
       int status=0;       //状态未知
       if(this._outSeqQueue.ContainsKey(seq)) //存在于outSeqQueue中
       {
        if(this._waitingSeqQueue.Contains(seq))
        {
         //正在发送等待返回,状态未定
        }
        else
        {
         //还没有发送
        }
       }
       else
       {
        if(this._waitingSeqQueue.ContainsKey(seq))
        {
         //正等待回应
        }
        else
        {
         //已经发送结束了
        }
       }
       return(status);
      }
      
      public void TestSubmit( string[] nums ,int topI,int topJ)  //发送测试包
      {
       int count=0;
       int total=0;   
       ArrayList pks=new ArrayList( );
       //准备100个包
       for(int i=0;i<10;i++)
       {
        for(int j=0;j<10;j++)
        {
         uint seq=this.getNextSequence(); //准备流水号
         MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq);
         sndmsg.FeeCode ="000001";
         sndmsg.FeeTerminalId =nums[i];
         sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM; //按条收取
         sndmsg.FeeUserType = 0 ;  //终端用户计费
         sndmsg.Msg_Level=0;
         sndmsg.MSGFormat = (uint)MSG.Msg_Format.UCS2;
         sndmsg.SMS_Content="test";
         sndmsg.SrcID="09880";         //长号码
         sndmsg.SPID=this.systemID ;
         sndmsg.Svc_Code= "cmcctest";
         sndmsg.UDHI=0;
         sndmsg.ValIdTime=getValIdTime(DateTime.Now);        //存活时间
         sndmsg.addTerminalID(nums[i]);
         pks.Add( sndmsg.toBytes()) ;   //存入数组
        }
       }
     
       DateTime t1=DateTime.Now ;
       for(int i=0;i< topI;i++)
       {  
        for(int j=0;j<topJ;j++)
        {
         try
         {
          tcp.Send((byte[])pks[i*10+j]);
          count++;
          total++;
         }
         catch (SocketException se)
         {
          this.ErrorInfo =this.ErrorInfo +"\r\n"+"发送错误: "+se.ToString() ;
         }   
         if( count>=16)
         {
          count=0;  //复位
          Thread.Sleep(50);  //暂停20ms
         }
        }
       }
       DateTime t2=DateTime.Now ;
       TimeSpan t= t2-t1;
       this.ErrorInfo =this.ErrorInfo +"\r\n"+"发送: "+total +" 条消息, 总计花费时间:"+ t.TotalMilliseconds +"毫秒" ;
      }  //测试函数////////////////////////////////////////////////供测试移动网络测试
      
      //测试翰数区域///////////////////////////////////////////
      //公用函数 属性区域////////////////////////////////////////
     }
     //*************工具类结束***********************************
     enum MSG_STATE     //CMPP消息在队列中的状态枚举值
     {
      NEW=0,      //加入到队列等待发送出去
      SENDING=1,     //正被某个线程锁定
      SENDED_WAITTING=2,   //发送出去,现在等待resp消息返回
      SENDING_FINISHED=3   //得到回应,一般等待被清理出队列
     }
     
     public class QueueItem   //代表一个存储在缓存队列中的消息,序列号由CMPPClient产生
     {
      uint _sequence;    //消息索引 就是流水号
      uint _msgType;    //消息的类别就是COMMAND_ID,根据此值决定 Object _msgObj的原类型
      int _failedCount=0;   //失败计数,如果失败次数超过3此需要进行清理
      int _msgState;    //当前消息状态,具体为 MSG_STATE的枚举类型
      object _msgObj;    //存放消息对象,具体类型参考 _msgType
      DateTime _inQueueTime;  //消息进入队列的时间,上次消息的发送时间
     
      public int FailedCount
      {
       set
       {
        this._failedCount =value;
       }
       get
       {
        return(this._failedCount);
       }
     
      }
     
      public object getMsgObj()
      {
       return(this._msgObj);
      }
      public void setmsgObj(object inmsg)
      {
       this._msgObj=inmsg;
      }
      public DateTime inQueueTime
      {
       set
       {
        this._inQueueTime =value;
       }
       get
       {
        return(this._inQueueTime);
       }
      }
      public uint MsgType
      {
       get
       {
        return(this._msgType);
       }
      }
      public int MsgState
      {
       get
       {
        return(this._msgState);
       }
       set
       {
        this._msgState =value;
       }
      }
      public uint Sequence
      {
       get
       {
        return(this._sequence);
       }
       set
       {
        this._sequence =value;
       }
      }
      public QueueItem(uint sequence,uint  msgtype ,int faildedcount,int msgstate)
      {
       this._failedCount =faildedcount;
       this._msgState =msgstate;
       this._msgType =msgtype;
       this._sequence=sequence;
      }
      public QueueItem(uint sequence,uint msgtype,int faildedcount,int msgstate,object msgobj)
      {
       this._failedCount =faildedcount;
       this._msgState =msgstate;
       this._msgType =msgtype;
       this._sequence=sequence;
       this.setmsgObj(msgobj);
      }
     }
     
     public class BIConvert  //字节 整形 转换类 网络格式转换为内存格式
     {
      public static byte[] Int2Bytes(uint i)  //转换整形数据网络次序的字节数组
      {
       byte[] t=BitConverter.GetBytes(i) ;
       byte b=t[0];
       t[0]=t[3];
       t[3]=b;
       b=t[1];
       t[1]=t[2];
       t[2]=b;
       return(t);
      }
     
      public static uint Bytes2UInt(byte[] bs,int startIndex) //返回字节数组代表的整数数字,4个数组
      {
       byte[] t=new byte[4];
       for(int i=0;i<4 && i< bs.Length-startIndex ;i++)
       {
        t[i]=bs[startIndex+i];
       } 
       byte b=t[0];
       t[0]=t[3];
       t[3]=b;
       b=t[1];
       t[1]=t[2];
       t[2]=b;
       return(BitConverter.ToUInt32(t,0));
      }
     
      public static uint Bytes2UInt(byte[] bs)  //没有指定起始索引
      {
       return( Bytes2UInt(bs,0));
      }

      public static void  DumpBytes(byte[] bs,string txt)
      {
       System.IO.StreamWriter sw=new System.IO.StreamWriter(txt);
       for(int i=0;i<bs.Length ;i++)
       {
        byte b=bs[i];
        sw.WriteLine(b.ToString("X")+" ");
       }
       sw.WriteLine("-----"+DateTime.Now.ToLocalTime()  );
       sw.Close();
      }

      public static void  DebugString(string  bs,string txt)
      {
       System.IO.StreamWriter sw=new System.IO.StreamWriter(txt);
       sw.WriteLine(bs); 
       sw.WriteLine("-----"+DateTime.Now.ToLocalTime()  );
       sw.Close();
      }
     }
     
     public class ReportEventArgs : EventArgs   //报告事件携带的数据
     {
      string _smsState;      //发送短信的应答结果,含义与SMPP协议要求中stat字段定义相同 。SP根据该字段确定CMPP_SUBMIT消息的处理状态。
      string _submitTime;      //提交短信的时间,也可根据此时间决定是否重发
      string _doneTime;      //送达目的地的时间
      string _destNum;      //送达的号码
      string _msgID;       //关于那一条消息的报告
      uint _sequence;       //CMPP网关产生的流水号

      UInt64 _msg_id;   //被报告的提交短信的msgID,ISMG在submit_resp返回给SP的

      public string State
      {
       get
       {
        return(this._smsState);
       }
       set
       {
        this._smsState =value;
       }
      }
     
      public uint Sequence
      {
       get
       {
        return(this._sequence );
       }
       set
       {
        this._sequence =value;
       }
      }
     
      public string toUserNum
      {
       get
       {
        return(this._destNum);
       }
       set
       {
        this._destNum =value;
       }
      }
     
      public string MsgID
      {
       get
       {
        return( this._msgID );
       }
       set
       {
        this._msgID =value;
       }
      }
     
      public string SubmitTime
      {
       get
       {
        return(this._submitTime);
       }
       set
       {
        this._submitTime =value;
       }
      }
     
      public string DoneTime
      {
       get
       {
        return(this._doneTime );
       }
       set
       {
        this._doneTime =value;
       }
      }
     
      public ReportEventArgs(byte[] bs)  //从一个字节数组中获得报告
      {
       byte[] temp=new byte[8+7+10+10+21+4];
       for(int i=0;i<temp.Length;i++)
       {
        temp[i]=bs[i];
       }
       init(temp);
      }
     
      public ReportEventArgs(byte[] bs,int startIndex) //起始
      {
       byte[] temp=new byte[8+7+10+10+21+4];//定义长度
       for(int i=0;i<temp.Length;i++)
       {
        temp[i]=bs[startIndex+i];
       }
       init(temp);
      }
     
      public ReportEventArgs(string msgid,string destnum,string smsstate,string submittime,string donetime,uint seq)
      {
       this._msgID =msgid;
       this._destNum =destnum;
       this._smsState =smsstate;
       this._submitTime =submittime;
       this._doneTime =donetime;
       this._sequence =seq;
      }
     
      public DateTime getSubmitTime()
      {
       return(getTime(this._submitTime));
      }
     
      public DateTime getDoneTime()
      {
       return(getTime(this._doneTime));
      }
     
      private DateTime getTime(string time_string)
      {
       int index=0;
       int yy=Convert.ToInt32("20"+ time_string.Substring(index,2));   
       index+=2;
       int mm=Convert.ToInt32(time_string.Substring(index,2));
       index+=2;
       int dd=Convert.ToInt32(time_string.Substring(index,2));
       index+=2;
       int hh=Convert.ToInt32(time_string.Substring(index,2));
       index+=2;
       int mms=Convert.ToInt32(time_string.Substring(index,2));
       DateTime t=new DateTime(yy,mm,dd,hh,mms,0);   
       return(t);
      }
      private void init(byte[] bs)
      {
       BIConvert.DumpBytes(bs,"c:\\ReportEventArgs.txt");//保留映像
       int index=0;
       this._msg_id =BitConverter.ToUInt64(bs,index);   //BitConverter.ToUInt64(bs,index);
       this._msgID =(this._msg_id.ToString());
               // BIConvert.DebugString(this._msgID ,"c:\\MSGID.txt"); 
       index +=8;
       this._smsState = Encoding.ASCII.GetString(bs,index,7);
       index+=7;
       this._submitTime = Encoding.ASCII.GetString(bs,index,10);
       index+=10;
       this._doneTime  = Encoding.ASCII.GetString(bs,index,10);
       index+=10;
       this._destNum = Encoding.ASCII.GetString(bs,index,21);
       index+=21;
       this._sequence = BIConvert.Bytes2UInt(bs,index);
      }
     }
     
     public class SMSEventArgs : EventArgs
     {
      UInt64 _msgid;    //8字节的消息标示
      string _destID;   //接受信息的目标ID
      string _svcCode;    //业务代码
      int  _tpPID;    //参考GSM协议
      int  _tpUDHI;   //
      int  _msgFrm;   //消息的编码格式
      string _srcTerminateID;  //源终端ID,如果使报告
      int  _msgLength;   //消息的字节数,并非实际字符串长度
      string _Content;   //消息正文内容
     

      public SMSEventArgs(byte[] bs)
      {
       int msglen=BitConverter.ToInt32(bs,8+21+10+1+1+1+21+1);  //取得消息长度字节长度
       int tempLen=msglen+8+21+10+1+1+1+21+1+1+msglen+8;
       byte[] temp=new byte[tempLen];
       for(int i=0;i<temp.Length ;i++)
       {
        temp[i]=bs[i];
       }
       init(temp);
      }
     
      public SMSEventArgs(byte[] bs,int baseIndex)
      {
       int msglen= (int)bs[MSG.CMPP_MSG_Header.HeaderLength +8+21+10+1+1+1+21+1];  //取得消息长度字节长度
       int tempLen=8+21+10+1+1+1+21+1+1+msglen+8;
       byte[] temp=new byte[tempLen];
       for(int i=0;i<temp.Length ;i++)
       {
        temp[i]=bs[i+baseIndex];
       }
       init(temp);
      }
     
      private void init(byte[] bs)
      {
       BIConvert.DumpBytes(bs,"c:\\SMSEventArgs.txt");//保留映像

       int index=0;
       this._msgid = BitConverter.ToUInt64(bs,0);
       index+=8;
       this._destID = Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
       index+=21;
       this._svcCode = Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
       index+=10;
       this._tpPID =(int)bs[index++];
       this._tpUDHI  =(int)bs[index++];
       this._msgFrm = (int)bs[index++];
       this._srcTerminateID =Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
       index+=21;
       index++;        //是否是状态报告字节
       this._msgLength = (int)bs[index++];  //取得字节长度
      
       switch ( this._msgFrm )
       {
        case (int)MSG.Msg_Format.ASCII :
         this._Content =Encoding.ASCII.GetString(bs,index,this._msgLength );
         break;
     
        case (int)MSG.Msg_Format.GB2312 :
         this._Content = Encoding.Default.GetString(bs,index,this._msgLength ); 
         break;
     
        case (int)MSG.Msg_Format.UCS2 :
         this._Content = Encoding.BigEndianUnicode.GetString(bs,index,this._msgLength );
         break;
     
        case (int)MSG.Msg_Format.BINARY :
         break;
     
        case (int)MSG.Msg_Format.WRITECARD :
         break;
     
        default:
         break;
     
       }
     
      }
     
      public string toSPNum
      {
       get
       {
        return(this._destID );
       }
      }
     
      public string SrcNum
      {
       get
       {
        return(this._srcTerminateID);
       }
      }
     
      public string Content
      {
       get
       {
        return(this._Content );
       }
      }
      public string SvcCode
      {
       get
       {
        return(this._svcCode);
       }
      }

      public UInt64  MsgID
      {
       get
       {
        return(this._msgid) ;
       }
       //set
       //{
       // this._msgid =value;
       //}
      }

      public string MsgIDString
      {
       get
       {
        return(this._msgid).ToString(); 
       }
      }

      private int  _getRealBytesLength(byte[] bts,int index)
      {
       int i=index;
       for( ;i<bts.Length ;i++)
       {
        if(bts[i]==0)
        {
         break;
        }
       }
       return i-index;
      }
     }
     
     public class TerminateEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_TERMINATE _msg;
     
      public TerminateEventArgs( uint seq)
      {
       this._seq =seq;
      }
     
      public TerminateEventArgs(object msg)
      {  
       this._msg =(MSG.CMPP_MSG_TERMINATE)msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg);
      }
      
     }
     
     public class TerminateRespEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_TERMINATE_RESP _msg;
     
      public TerminateRespEventArgs(uint seq)
      {
       this._seq =seq;
      }
     
      public TerminateRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_TERMINATE_RESP)msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg );
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq);
       }
      }
     }
     public class TestEventArgs: EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_TEST _msg;
     
      public TestEventArgs(uint seq)
      {
       this._seq =seq;
      }
     
      public  TestEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_TEST)msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg );
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq );
       }
      }
     }
     
     public class TestRespEventArgs: EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_TEST_RESP _msg;
     
      public TestRespEventArgs(uint seq)
      {
       this._seq =seq;
      }
      public TestRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_TEST_RESP)msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg );
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq);
       }
      }
     }
     
     public class CancelRespEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_CANCEL_RESP _msg;
     
      public CancelRespEventArgs(uint seq)
      {
       this._seq =seq;
      }
      public CancelRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_CANCEL_RESP) msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg);
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq );
       }
      }
     }
     
     public class QueryRespEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_QUERY_RESP _msg;
     
      public QueryRespEventArgs(uint seq)
      {
       this._seq =seq;  
      }
     
      public QueryRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_QUERY_RESP)msg;
       this._seq =this._msg.Sequence; 
      }
     
      public object getMSG()
      {
       return(this._msg);
      }
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq);
       }
      }
     
     }
     
     public class ConnectRespEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_CONNECT_RESP _msg;
     
      public ConnectRespEventArgs(uint seq)
      {
       this._seq =seq;
      }
     
      public ConnectRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_CONNECT_RESP)msg;
       this._seq =this._msg.Sequence ;
      }
     
      public object getMSG()
      {
       return(this._msg );
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq );
       }
      }
     }
     
     public class SubmitRespEventArgs:EventArgs
     {
      private uint _seq;
      private MSG.CMPP_MSG_SUBMIT_RESP _msg;  
     
      public SubmitRespEventArgs(uint seq)
      {
       this._seq =seq;   
      }
      public SubmitRespEventArgs(object msg)
      {
       this._msg =(MSG.CMPP_MSG_SUBMIT_RESP)msg;
       this._seq=this._msg.Sequence ;
      }
      public object getMSG()
      {
       return(this._msg );
      }
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq );
       }
      }
     }
     
     public class WaitingQueueItemEventArgs:EventArgs
     {
      private uint _seq;
      private object _q;
     
      public WaitingQueueItemEventArgs(uint seq)
      {
       this._seq =seq;
      }
     
      public WaitingQueueItemEventArgs(object q)
      {
       this._q =q;
      }
     
      public uint Sequence
      {
       set
       {
        this._seq =value;
       }
       get
       {
        return(this._seq );
       }
      }
     
      public object getQueueItem()
      {
       return(this._q );
      }
     }

     public class ClientQueueStateArgs  //当CMPP client的服务停止时候,队列的状态参数
     {
      private SortedList _waiting;
      private SortedList _out;

      public ClientQueueStateArgs(SortedList outQueue,SortedList inQueue)
      {
       this._waiting =inQueue;
       this._out =outQueue;
      }

      public SortedList WaitingQueue
      {
       get
       {
        return(this._waiting );
       }
       set
       {
        this._waiting =value;
       }
      }

      public SortedList OutQueue
      {
       get
       {
        return(this._out );
       }
       set
       {
        this._out =value;
       }
      }
     }

     public class StateObject
     {
      public Socket workSocket = null;              // Client socket.
      public const int BufferSize = 1024;            // Size of receive buffer.
      public byte[] buffer = new byte[BufferSize];  // Receive buffer.
      public byte[] result_buf=null;     //接收最终的结果缓冲区  
      public int _msglength=0;      //接收到多少个字节数据
     }


     
     public enum SMSDBQueue_Status  :int
     {
      NEW=0,   //新消息,等待发送
      SENDED=1,  //正在发送,等待回应
      RESP=2,   //送达SMSC,得到msgid
      DELIVRD=3,  //得到报告,状态ok
      EXPIRED=4,  //过期
      DELETED=5,  //已经删除此消息 UNDELIV
      ACCEPTD=6,  // ACCEPTD 状态 未送达 ACCEPTED为中间状态,网关若从短信中心收到后应丢弃,不做任何操作
      UNDELIV=7,  //未送达
      UNKNOWN=8,  //未知
      REJECTD=9   //被弹回
     }

     public class SMSDBQueue
     {
      private uint _sequence=0;      //对应的cmppclient的序列号
      private int _smsdbID=0;       //对应的数据库的发送自动增长ID
      private int _cmpp_msgType;      //cmpp协议的定义的消息类型
      private object _cmpp_msg_object;    //cmpp消息对象,备检索
      private int _currentStatus;      //当前消息体状态
      private DateTime _inQueueTime=DateTime.Now;  //消息产生设定值
      private UInt64 _msgid;       //消息返回的SMSC给出的id遍号

      public uint Sequence
      {
       get
       {
        return(this._sequence );
       }
       set
       {
        this._sequence =value;
       }
      }

      public int SMSDBID
      {
       get
       {
        return(this._smsdbID);
       }
       set
       {
        this._smsdbID =value;
       }
      }

      public int CurrentStatus
      {
       get
       {
        return(this._currentStatus );
       }
       set
       {
        this._currentStatus =value;
       }
      }

      public int CMPPMsgType
      {
       get
       {
        return(this._cmpp_msgType );
       }
       set
       {
        this._cmpp_msgType =value;
       }
      }

      public DateTime InQueueTime
      {
       get
       {
        return(this._inQueueTime );
       }
       set
       {
        this._inQueueTime =value;
       }
      }

      public object MsgObject
      {
       get
       {
        return(this._cmpp_msg_object );
       }
       set
       {
        this._cmpp_msg_object =value;
       }
      }       

      public UInt64 UIMsgID
      {
       get
       {
        return(this._msgid );
       }
       set
       {
        this._msgid =value;
       }
      }

      public string MsgID
      {
       get
       {
        return(this._msgid.ToString ());
       }
       set
       {
        this._msgid =Convert.ToUInt64(value);
       }
      }
     }
     //*************工具类结束***********************************


     //********************接口类,用于连接对外的短信存储系统**********************
     public interface  ISMSStore   //定义一个存储接口
     {
      SMSRec[] getSMSsFromStore();    &n