⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smgp3_0.cs

📁 这个是基于SMPP的开发源码
💻 CS
字号:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

namespace SMGP3_0
{
	public delegate void SendEventHandler(SMGPConnection Sender, Guid ID, byte[] MsgID, Int32 Status);
	public delegate void DeliverEventHandler(SMGPConnection Sender, byte[] MsgID, byte IsReport, byte MsgFormat, string RecvTime, string SrcTermID, string DestTermID, byte[] MsgContent, byte[] Reserve, params SMPP.Variable.TLV[] TLVFields);
	public delegate void ConnectStateEventHandler(SMGPConnection Sender);

	public partial class SMGPConnection : Component
	{
		private delegate void ReceivePackEventHandler(SMGPPack Pack);
		private event ReceivePackEventHandler OnPackResponse;
		private event ReceivePackEventHandler OnReceiveRequest;

		private static Initialize Init = new Initialize();

		public event SendEventHandler OnSend;
		public event DeliverEventHandler OnDeliver;
		public event ConnectStateEventHandler OnConnect;
		public event ConnectStateEventHandler OnDisconnect;

		public SMGPConnection()
		{
			InitializeComponent();
			Setup();
		}

		public SMGPConnection(IContainer container)
		{
			container.Add(this);

			InitializeComponent();
			Setup();
		}

		private object _Tag;
		public object Tag
		{
			get
			{
				return _Tag;
			}
			set
			{
				_Tag = value;
			}
		}

		/// <summary>
		/// 服务器地址
		/// </summary>
		public string ServerIP
		{
			get
			{
				return cs.RemoteAddress;
			}
		}

		/// <summary>
		/// 服务器端口
		/// </summary>
		public int ServerPort
		{
			get
			{
				return cs.RemotePort;
			}
		}

		private int SequeceID = 1;

		/// <summary>
		/// 数据包超时设置(秒)
		/// </summary>
		public int TimeOut
		{
			get
			{
				return Queue.TimeOut;
			}
			set
			{
				Queue.TimeOut = value;
			}
		}

		private int TimeOutCount = 0;
		private int _MaxTimeOutCount = 3;
		/// <summary>
		/// 最大超时数(数据包超时超过此值网关就自动断开连接)
		/// </summary>
		public int MaxTimeCount
		{
			get
			{
				return _MaxTimeOutCount;
			}
			set
			{
				_MaxTimeOutCount = value;
			}
		}

		private int _WindowSize = 16;

		/// <summary>
		/// 滑动窗口大小
		/// </summary>
		public int WindowSize
		{
			get
			{
				return _WindowSize;
			}
			set
			{
				_WindowSize = value;
			}
		}

		/// <summary>
		/// 当前滑动窗口数
		/// </summary>
		public int Window
		{
			get
			{
				return Queue.Count;
			}
		}

		private bool _Logined = false;
		/// <summary>
		/// 网关是否已经登录
		/// </summary>
		public bool Logined
		{
			get
			{
				return _Logined;
			}
		}

		public enum EVersion : byte
		{
			SMGP1_3 = 0x13,
			SMGP2_0 = 0x20,
			SMGP3_0 = 0x30
		}

		private EVersion _ClientVersion = EVersion.SMGP1_3;
		/// <summary>
		/// 网关客户端版本号
		/// </summary>
		public EVersion ClientVersion
		{
			get
			{
				return _ClientVersion;
			}
			set
			{
				_ClientVersion = value;
			}
		}

		private PackList Queue = new PackList();
		private DataBuffer Buffer = new DataBuffer();

		private void Setup()
		{
			Queue.TimeOut = TimeOut;

			Queue.OnPackTimeOut += new PackList.PackTimeOutEventHandler(Queue_OnPackTimeOut);

			Buffer.OnParsePack += new DataBuffer.ParsePackEventHandler(Buffer_OnParsePack);
			Buffer.OnRaiseError += new DataBuffer.RaiseErrorEventHandler(Buffer_OnRaiseError);

			OnPackResponse += new ReceivePackEventHandler(SMGP3_0_OnPackResponse);
			OnReceiveRequest += new ReceivePackEventHandler(SMGP3_0_OnReceiveRequest);
		}

		void Queue_OnPackTimeOut(PackList Sender, SMGPPack Pack)
		{//数据包超时未反馈
			TimeOutCount++;

			if (TimeOutCount > _MaxTimeOutCount)
			{//如果超过最大超时数则关闭连接
				cs.Close();
				return;
			}

			UInt32 RequestID = (UInt32)Pack.Header.RequestID;

			switch (RequestID)
			{
				case 0x00000002:
					{
						if (OnSend != null)
							OnSend(this, Pack.ID, null, -1);
						break;
					}
				case 0x00000004:
					{//重发链路检测包
						SendRequest(Pack);
						break;
					}
			}
		}

		void SMGP3_0_OnReceiveRequest(SMGPPack Pack)
		{//接收到请求包
			UInt32 RequestID = (UInt32)Pack.Header.RequestID;
			switch (RequestID)
			{
				case 0x00000003:
					{
						SMGPBody_Deliver bd = Pack.Body as SMGPBody_Deliver;
						SMGPBody_Deliver_Resp dr = new SMGPBody_Deliver_Resp();
						SMGPPack pk = new SMGPPack(dr);

						dr.MsgID = (Pack.Body as SMGPBody_Deliver).MsgID;
						dr.Status = 0;
						SendSMGP(pk);

						if (OnDeliver != null)
							OnDeliver.BeginInvoke(this, bd.MsgID, bd.IsReport, bd.MsgFormat, bd.RecvTime, bd.SrcTermID, bd.DestTermID, bd.MsgContent, bd.Reserve, bd.TLVFields.GetArray(), null, null);
						break;
					}
				case 0x00000004:
					{
						SMGPPack pk = new SMGPPack(new SMGPBody_Active_Resp());
						SendSMGP(pk);
						break;
					}
			}
		}

		void SMGP3_0_OnPackResponse(SMGPPack Pack)
		{//接收到应答包
			SMGPPack Response = (SMGPPack)Pack.Tag;
			UInt32 RequestID = (UInt32)Response.Header.RequestID;
			switch (RequestID)
			{
				case 0x80000001:
					{
						break;
					}
				case 0x80000002:
					{
						SMGPBody_Submit_Resp sr = Response.Body as SMGPBody_Submit_Resp;
						if (OnSend != null)
							OnSend.BeginInvoke(this, Pack.ID, sr.MsgID, sr.Status, null, null);
						break;
					}
				case 0x80000006:
					{
						cs.Close();
						break;
					}
			}
		}

		void Buffer_OnRaiseError(DataBuffer Sender, Exception Error)
		{//缓冲区发生错误(建议重新连接网关)
			cs.Close();
		}

		void Buffer_OnParsePack(DataBuffer Sender, SMGPPack Pack)
		{
			UInt32 RequestID = (UInt32)Pack.Header.RequestID;

			if (RequestID >= 0x80000001)
			{
				SMGPPack Request = Queue.GetPackBySequenceID(Pack.Header.SequenceID);
				if (Request != null)
				{
					Queue.Remove(Request);
					Request.Tag = Pack;
					OnPackResponse.BeginInvoke(Request, null, null);
				}
			}
			else
			{
				OnReceiveRequest.BeginInvoke(Pack, null, null);
			}
		}

		private void SendSMGP(SMGPPack Pack)
		{
			byte[] Data = Pack.GetBytes();
			cs.Send(Data);
		}

		private void SendRequest(SMGPPack Pack)
		{
			while (Window >= WindowSize)
				Thread.Sleep(300);

			Pack.Header.SequenceID = SequeceID++;
			Queue.Add(Pack);
			SendSMGP(Pack);
		}

		#region 方法
		/// <summary>
		/// 连接到SMGP服务器
		/// </summary>
		/// <param name="ServerIP">服务器地址</param>
		/// <param name="ServerPort">服务器端口</param>
		/// <returns>成功返回true,否则返回false</returns>
		public bool Connect(string ServerIP, int ServerPort)
		{
			bool Ret;
			cs.RemoteAddress = ServerIP;
			cs.RemotePort = ServerPort;
			Ret = cs.Open();
			return Ret;
		}

		/// <summary>
		/// 断开连接
		/// </summary>
		public void Disconnect()
		{
			cs.Close();
		}

		/// <summary>
		/// 登录到SMGP服务器
		/// </summary>
		/// <param name="ClientID">用户账号</param>
		/// <param name="Password">登录密码</param>
		/// <param name="LoginMode">登录模式</param>
		/// <returns>成功返回true,否则返回false</returns>
		public bool Login(string ClientID, string Password, EConnectorType LoginMode)
		{
			bool ret = false;

			SMGPBody_Login login = new SMGPBody_Login();
			login.ClientID = ClientID;
			login.ClientVersion = (byte)ClientVersion;
			switch (LoginMode)
			{
				case EConnectorType.Transmitter:
					{
						login.LoginMode = 0;
						break;
					}
				case EConnectorType.Receiver:
					{
						login.LoginMode = 1;
						break;
					}
				case EConnectorType.Transceiver:
					{
						login.LoginMode = 2;
						break;
					}
				default:
					{
						login.LoginMode = 0;
						break;
					}
			}

			string TimeStamp = DateTime.Now.ToString("MMddHHmmss");

			login.TimeStamp = int.Parse(TimeStamp);

			byte[] clientid = System.Text.Encoding.ASCII.GetBytes(ClientID);
			byte[] password = System.Text.Encoding.ASCII.GetBytes(Password);
			byte[] timestamp = System.Text.Encoding.ASCII.GetBytes(TimeStamp);

			byte[] data = new byte[clientid.Length + 7 + password.Length + timestamp.Length];

			Array.Copy(clientid, data, clientid.Length);

			Array.Copy(password, 0, data, clientid.Length + 7, password.Length);

			Array.Copy(timestamp, 0, data, clientid.Length + 7 + password.Length, timestamp.Length);

			System.Security.Cryptography.MD5 MD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

			login.AuthenticatorClient = MD5.ComputeHash(data);

			SMGPPack pk = new SMGPPack(login);

			SendRequest(pk);

			DateTime DT = DateTime.Now;
			while (pk.Tag == null && (DateTime.Now - DT).TotalSeconds < TimeOut && cs.IsActive)
			{
				Thread.Sleep(300);
			}

			if (pk.Tag != null && (pk.Tag as SMGPPack).Body.GetType().Equals(typeof(SMGPBody_Login_Resp)))
			{
				SMGPBody_Login_Resp resp = (pk.Tag as SMGPPack).Body as SMGPBody_Login_Resp;

				ret = resp.Status == 0 ? true : false;
			}

			_Logined = ret;
			return ret;
		}

		/// <summary>
		/// 从SMGP服务器注销
		/// </summary>
		public void Logout()
		{
			if (Logined)
			{
				SMGPBody_Exit be = new SMGPBody_Exit();
				SMGPPack pk = new SMGPPack(be);

				SendRequest(pk);
			}
		}

		/// <summary>
		/// 发送短消息
		/// </summary>
		/// <param name="ID">该条信息的唯一标识</param>
		/// <param name="MsgType">短消息类型</param>
		/// <param name="NeedReport">是否需要状态报告</param>
		/// <param name="Priority">短消息优先级</param>
		/// <param name="ServiceID">业务代码</param>
		/// <param name="FeeType">收费类型</param>
		/// <param name="FeeCode">点播费用</param>
		/// <param name="FixedFee">包月费/封顶费</param>
		/// <param name="MsgFormat">短消息格式</param>
		/// <param name="ValidTime">短消息有效时间</param>
		/// <param name="AtTime">短消息定时发送时间</param>
		/// <param name="SrcTermID">短消息发送方号码</param>
		/// <param name="ChargeTermID">计费用户号码</param>
		/// <param name="DestTermIDCount">短消息接收号码总数</param>
		/// <param name="DestTermID">短消息接收号码</param>
		/// <param name="MsgLength">短消息长度</param>
		/// <param name="MsgContent">短消息内容</param>
		/// <param name="Reserve">保留</param>
		/// <param name="TLVFields">TLV字段列表</param>
		/// <returns>可以发送返回true,否则返回false</returns>
		public bool SendMessage(Guid ID, byte MsgType, byte NeedReport, byte Priority, string ServiceID, string FeeType, string FeeCode, string FixedFee, byte MsgFormat, string ValidTime, string AtTime, string SrcTermID, string ChargeTermID, byte DestTermIDCount, string DestTermID, byte MsgLength, byte[] MsgContent, byte[] Reserve, params SMPP.Variable.TLV[] TLVFields)
		{
			bool ret = false;
			if (Logined)
			{
				SMGPBody_Submit submit = new SMGPBody_Submit();
				submit.MsgType = MsgType;
				submit.NeedReport = NeedReport;
				submit.Priority = Priority;
				submit.ServiceID = ServiceID;
				submit.FeeType = FeeType;
				submit.FeeCode = FeeCode;
				submit.FixedFee = FixedFee;
				submit.MsgFormat = MsgFormat;
				submit.ValidTime = ValidTime;
				submit.AtTime = AtTime;
				submit.SrcTermID = SrcTermID;
				submit.ChargeTermID = ChargeTermID;
				submit.DestTermIDCount = DestTermIDCount;
				submit.DestTermID = DestTermID;
				submit.MsgLength = MsgLength;
				submit.MsgContent = MsgContent;
				submit.Reserve = Reserve;

				foreach (SMPP.Variable.TLV tlv in TLVFields)
					submit.TLVFields.Add(tlv);

				SMGPPack pk = new SMGPPack(submit);
				pk.ID = ID;

				SendRequest(pk);

				ret = true;
			}

			return ret;
		}

		/// <summary>
		/// 发送短消息
		/// </summary>
		/// <param name="ID">该条信息的唯一标识</param>
		/// <param name="MsgType">短消息类型</param>
		/// <param name="NeedReport">是否需要状态报告</param>
		/// <param name="Priority">短消息优先级</param>
		/// <param name="ServiceID">业务代码</param>
		/// <param name="FeeType">收费类型</param>
		/// <param name="FeeCode">点播费用</param>
		/// <param name="FixedFee">包月费/封顶费</param>
		/// <param name="MsgFormat">短消息格式</param>
		/// <param name="ValidTime">短消息有效时间</param>
		/// <param name="AtTime">短消息定时发送时间</param>
		/// <param name="SrcTermID">短消息发送方号码</param>
		/// <param name="ChargeTermID">计费用户号码</param>
		/// <param name="DestTermIDCount">短消息接收号码总数</param>
		/// <param name="DestTermID">短消息接收号码</param>
		/// <param name="MsgContent">短消息内容</param>
		/// <param name="Reserve">保留</param>
		/// <param name="TLVFields">TLV字段列表</param>
		/// <returns>可以发送返回true,否则返回false</returns>
		public bool SendMessage(Guid ID, byte MsgType, byte NeedReport, byte Priority, string ServiceID, string FeeType, string FeeCode, string FixedFee, byte MsgFormat, string ValidTime, string AtTime, string SrcTermID, string ChargeTermID, byte DestTermIDCount, string DestTermID, string MsgContent, byte[] Reserve, params SMPP.Variable.TLV[] TLVFields)
		{
			SMPP.Variable.Encoding Encoder = new SMPP.Variable.Encoding();
			Encoder.Value = MsgFormat;

			byte[] Message = Encoder.Encoder.GetBytes(MsgContent);

			return SendMessage(ID, MsgType, NeedReport, Priority, ServiceID, FeeType, FeeCode, FixedFee, MsgFormat, ValidTime, AtTime, SrcTermID, ChargeTermID, DestTermIDCount, DestTermID, Message.Length > byte.MaxValue ? byte.MaxValue : (byte)Message.Length, Message, Reserve, TLVFields);
		}
		#endregion

		private void cs_OnConnect(object Sender)
		{
			_MaxTimeOutCount = 0;
			Buffer.Start();
			Queue.Start();
			if (OnConnect != null)
				OnConnect.BeginInvoke(this, null, null);
		}

		private void cs_OnDisconnect(object Sender)
		{
			_Logined = false;
			Buffer.Stop();
			Queue.Stop();
			if (OnDisconnect != null)
				OnDisconnect.BeginInvoke(this, null, null);
		}

		private void cs_OnReceiveData(object Sender, byte[] Datas)
		{
			Buffer.Fill(Datas);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -