//附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(); //从外部存储中获取消息 void updateStoreObjec(int storeObjectID,string state); //更新id代表的对象状态,用于监测状态报告 void updateSMSCMsgID(int storeObjectID,UInt64 msgid); bool addSMS2Store(SMSRec sms); //向store中存储短消息 string getFeeCode(string svccode); //根据svccode返回消息的收费,根据移动参数进行设定 } public class SMSRec //SMS载数据库中的表达 { private int _RecID; private string _feeUser; //计费用户 private int _smsType=0; //短信类型 0 普通文字短信 1 闪烁短信 2 查询命令短信 3 包月短信 private string _svccode; //服务代码 private string _msg; //消息 private string _state; //消息状态 private string _feecode; private string _spnum; private string _toUser; public SMSRec(int recid,string feeuser,string feecode,string svccode,string msg,string spnum) { this._RecID =recid; this._feeUser =feeuser; this._toUser =feeuser; this._svccode =svccode; this._msg =msg; this._spnum =spnum; } public SMSRec(int recid,string feeuser,string touser,string feecode,string svccode,string msg,string spnum) { this._RecID =recid; this._feeUser =feeuser; this._toUser =touser; this._svccode =svccode; this._msg =msg; this._spnum =spnum; } public string SvcCode { get { return(this._svccode ); } set { this._svccode =value; } } public string FeeCode { get { return(this._feecode ); } set { this._feecode =value; } } public string FeeUser { get { return(this._feeUser ); } set { this._feeUser =value; } } private string ToUser { get { return(this._toUser); } set { this._toUser=value; } } public string SPNum { get { return(this._spnum ); } set { this._spnum =value; } } public string Message { get { return(this._msg ); } set { this._msg =value; } } } //****************************** 接口类结束 ********************************* //*************************定义 处理数据库接口的SMS系统类,该类对外提供CMPP处理功能*********** //**功能,实现队列监测,处理失败消息、成功消息,处理定时存储更新等抽象功能的组织,将CMPPClient包装提供 public class SMSSystem { private ISMSStore dbcls=null; private CMPPClient client=null; private string pwd; private string systemid;