namespace AsiaINFO.SMS.CMPP2 { using System; using System.Collections; using System.Collections.Generic; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Threading; public class CMPPClient { private bool _IsConnected; private NetworkStream _NetworkStream; private Thread _ReadResponseThread; private Queue _receiveQueue; private string _Source_Addr; private SyncEvents _syncEvents; private object _syncIsConnectedObject = new object(); private static object _SyncLockObject = new object(); private TcpClient tc; public event MsgEventDelegate ErrorEvent; public event MsgEventDelegate MsgEvent; public event ThreadStateDelegate ThreadStateEvent; public CMPPClient(Queue queue, SyncEvents cmppSyncEvents) { if ((queue == null) || (cmppSyncEvents == null)) { throw new Exception("参数不能为空!"); } this._receiveQueue = queue; this._syncEvents = cmppSyncEvents; } public void ActiveResp(uint SequenceId) { this.WriteToStreamWithLock(new CMPP_ACTIVE_TEST_RESP(SequenceId).ToBytes(), this._NetworkStream); } public void ActiveTest(uint SequenceId) { this.WriteToStreamWithLock(new MessageHeader(12, CMPP_Command_Id.CMPP_ACTIVE_TEST, SequenceId).ToBytes(), this._NetworkStream); } public void Connect(string Host, int Port, string UserID, string Password, uint SequenceId) { this._Source_Addr = UserID; CMPP_CONNECT cmpp_connect = new CMPP_CONNECT(this._Source_Addr, Password, DateTime.Now, 0x20, SequenceId); this.tc = new TcpClient(); this.tc.Connect(Host, Port); if (this._NetworkStream != null) { try { this._NetworkStream.Close(); this._NetworkStream = null; } catch (Exception) { } } this._NetworkStream = this.tc.GetStream(); this.WriteToStreamWithLock(cmpp_connect.ToBytes(), this._NetworkStream); this.StartRun(); } public void DeliverResp(ulong Msg_Id, uint Result, uint SequenceId) { this.WriteToStreamWithLock(new CMPP_DELIVER_RESP(Msg_Id, Result, SequenceId).ToBytes(), this._NetworkStream); } public void Exit() { try { this.StopReceive(); this._NetworkStream.Close(); this._NetworkStream = null; } catch (Exception) { } } public bool IsStop() { if (((this._ReadResponseThread != null) && (this._ReadResponseThread.ThreadState != ThreadState.Stopped)) && ((this._ReadResponseThread.ThreadState != ThreadState.Aborted) && (this._ReadResponseThread.ThreadState != ThreadState.AbortRequested))) { return false; } return true; } private void OnError(string err) { if (this.ErrorEvent != null) { this.ErrorEvent(err); } } private void OnMsg(string msg) { if (this.MsgEvent != null) { this.MsgEvent(msg); } } protected void OnThreadState(ThreadState state) { if (this.ThreadStateEvent != null) { this.ThreadStateEvent(this, state); } } public void Query(DateTime Time, uint QueryType, string QueryCode, string Reserve, uint SequenceId) { this.WriteToStreamWithLock(new CMPP_QUERY(Time, QueryType, QueryCode, Reserve, SequenceId).ToBytes(), this._NetworkStream); } private byte[] ReadFromStreamWithLock(int Length, NetworkStream Stream) { try { lock (_SyncLockObject) { return Util.ReadFromStream(Length, Stream); } } catch (Exception exception) { this.IsConnected = false; this.OnError(exception.Message); } return null; } private void Run() { try { while (!this._syncEvents.ExitThreadEvent.WaitOne(2, false)) { if (this._NetworkStream.CanRead && this._NetworkStream.DataAvailable) { byte[] bytes = new byte[12]; bytes = this.ReadFromStreamWithLock(12, this._NetworkStream); MessageHeader header = new MessageHeader(bytes); byte[] dst = new byte[header.Total_Length]; Buffer.BlockCopy(bytes, 0, dst, 0, bytes.Length); int length = ((int) header.Total_Length) - 12; if (length > 0) { bytes = this.ReadFromStreamWithLock(length, this._NetworkStream); Buffer.BlockCopy(bytes, 0, dst, 12, bytes.Length); } lock (((ICollection) this._receiveQueue).SyncRoot) { this._receiveQueue.Enqueue(dst); } this._syncEvents.NewItemEvent.Set(); } } } catch (Exception exception) { this.IsConnected = false; this.OnError("CMPPClient接收错误:" + exception.Message); } this.OnThreadState(ThreadState.Stopped); } public void StartRun() { try { if (this._ReadResponseThread == null) { this._ReadResponseThread = new Thread(new ThreadStart(this.Run)); } if (this._ReadResponseThread.ThreadState == ThreadState.Unstarted) { this.OnThreadState(ThreadState.Running); this._ReadResponseThread.Start(); } else if (this._ReadResponseThread.ThreadState == ThreadState.Suspended) { this.OnThreadState(ThreadState.Running); this._ReadResponseThread.Resume(); } else if (this._ReadResponseThread.ThreadState == ThreadState.Stopped) { this.OnThreadState(ThreadState.Running); this._ReadResponseThread = null; this._ReadResponseThread = new Thread(new ThreadStart(this.Run)); this._ReadResponseThread.Start(); } } catch (Exception exception) { this.OnError("CMPPClient启动错误:" + exception.Message); } } public void StopImmediately() { try { if (this._ReadResponseThread != null) { this._ReadResponseThread.Abort(); } } catch (ThreadAbortException) { } catch (Exception) { } finally { this.OnThreadState(ThreadState.Stopped); } } public void StopReceive() { this._syncEvents.ExitThreadEvent.Set(); } public void Submit(ulong MsgId, string mobile, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL, uint MsgSum, uint MsgSub) { if ((mobile != null) && (mobile.Length == 11)) { mobile = "86" + mobile; } this.Submit(MsgId, mobile, new string[] { mobile }, MsgContent, SequenceId, Service_Id, FeeType, FeeCode, Src_Id, WapURL, MsgSum, MsgSub); } public void Submit(ulong MsgId, string FeeTerminalId, string[] DestTerminalId, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL, uint MsgSum, uint MsgSub) { this.Submit(MsgId, 1, 0, FeeTerminalId, DestTerminalId, MsgContent, SequenceId, Service_Id, FeeType, FeeCode, Src_Id, WapURL, MsgSum, MsgSub); } public void Submit(ulong MsgId, uint RegisteredDelivery, uint Fee_UserType, string FeeTerminalId, string[] DestTerminalId, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL, uint MsgSum, uint MsgSub) { CMPP_SUBMIT cmpp_submit; this.WriteToStreamWithLock(new CMPP_SUBMIT(SequenceId) { WapURL = WapURL, Msg_Id = MsgId, Pk_total = MsgSum, Pk_number = MsgSub, Registered_Delivery = RegisteredDelivery, Msg_level = 1, Service_Id = Service_Id, Fee_UserType = Fee_UserType, Fee_terminal_Id = "", TP_pId = 0, TP_udhi = 0, Msg_Fmt = 15, Msg_src = this._Source_Addr, FeeType = FeeType, FeeCode = FeeCode, ValId_Time = "", At_Time = "", Src_Id = Src_Id, Dest_terminal_Id = DestTerminalId, DestUsr_tl = (uint) cmpp_submit.Dest_terminal_Id.Length, Msg_Fmt = 15, Msg_Content = MsgContent, Reserve = "" }.ToBytes(), this._NetworkStream); } public void Suspend() { try { if (((this._ReadResponseThread != null) && (this._ReadResponseThread.ThreadState != ThreadState.Stopped)) && (this._ReadResponseThread.ThreadState != ThreadState.Suspended)) { this.OnThreadState(ThreadState.Suspended); this._ReadResponseThread.Suspend(); } } catch (Exception) { } } public void Terminate(uint SequenceId) { this.WriteToStreamWithLock(new MessageHeader(12, CMPP_Command_Id.CMPP_TERMINATE, SequenceId).ToBytes(), this._NetworkStream); } private void WriteToStreamWithLock(byte[] data, NetworkStream Stream) { try { lock (_SyncLockObject) { Util.WriteToStream(data, Stream); } } catch (Exception exception) { this.IsConnected = false; this.OnError(exception.Message); } } public bool IsConnected { get { lock (this._syncIsConnectedObject) { return this._IsConnected; } } set { lock (this._syncIsConnectedObject) { this._IsConnected = value; } } } public delegate void MsgEventDelegate(string msg); public delegate void ThreadStateDelegate(object sender, ThreadState state); } }