//附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 +" "+se.ToString ();
???}
???catch(NullReferenceException nre)
???{
????this._bNre =true;? //出現空引用錯誤
????this.ErrorInfo =this.ErrorInfo +" "+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 +" "+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 +" "+"收到: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 +" "+"發送:CMPP_ACTIVE_TEST_RESP ";
????????break;
?
???????case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP : //服務器的回應消息,應當丟棄不管
????????this.ErrorInfo =this.ErrorInfo +" "+("收到: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 +" "+("收到: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 +" "+("收到: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 +" "+("收到: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 +" "+("發送: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 +" "+("收到: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 +" "+("收到: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 +" "+"收到: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 +" "+"收到: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 +" "+"收到: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 +" "+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 + " "+" 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_