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<byte[]> _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<byte[]> 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)
|
{
|
this.OnMsg("接收到数据流...");
|
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();
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="MsgId"></param>
|
/// <param name="mobile"></param>
|
/// <param name="MsgContent"></param>
|
/// <param name="SequenceId"></param>
|
/// <param name="Service_Id">企业帐户如 hs0055</param>
|
/// <param name="FeeType"></param>
|
/// <param name="FeeCode"></param>
|
/// <param name="Src_Id">接入号:如 1069022600055</param>
|
/// <param name="WapURL"></param>
|
/// <param name="MsgSum"></param>
|
/// <param name="MsgSub"></param>
|
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);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="MsgId"></param>
|
/// <param name="FeeTerminalId">收费</param>
|
/// <param name="DestTerminalId"></param>
|
/// <param name="MsgContent"></param>
|
/// <param name="SequenceId"></param>
|
/// <param name="Service_Id">企业帐户如 hs0055</param>
|
/// <param name="FeeType">默认都为01</param>
|
/// <param name="FeeCode">0</param>
|
/// <param name="Src_Id">接入号:如 1069022600055</param>
|
/// <param name="WapURL"></param>
|
/// <param name="MsgSum"></param>
|
/// <param name="MsgSub"></param>
|
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);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="MsgId"></param>
|
/// <param name="RegisteredDelivery">1表示需要上报状态报告</param>
|
/// <param name="Fee_UserType"></param>
|
/// <param name="FeeTerminalId"></param>
|
/// <param name="DestTerminalId"></param>
|
/// <param name="MsgContent"></param>
|
/// <param name="SequenceId"></param>
|
/// <param name="Service_Id"></param>
|
/// <param name="FeeType"></param>
|
/// <param name="FeeCode"></param>
|
/// <param name="Src_Id"></param>
|
/// <param name="WapURL"></param>
|
/// <param name="MsgSum"></param>
|
/// <param name="MsgSub"></param>
|
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 submit = 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 = 8,
|
Msg_src = this._Source_Addr,
|
FeeType = FeeType,
|
FeeCode = FeeCode,
|
ValId_Time = "",
|
At_Time = "",
|
Src_Id = Src_Id,
|
Dest_terminal_Id = DestTerminalId,
|
DestUsr_tl = (uint)DestTerminalId.Length,
|
Msg_Content = MsgContent,
|
Reserve = ""
|
};
|
|
this.WriteToStreamWithLock(submit.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)
|
{
|
if (!Stream.CanWrite) throw new Exception("Cann't Write Stream!");
|
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);
|
}
|
}
|