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

📄 cngpprotocol.cs

📁 网通网关Cngp
💻 CS
📖 第 1 页 / 共 3 页
字号:
using System;
using System.Threading;
using System.Collections;
using WriteLog;
using System.Timers;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Pierce.AttributeClass;
namespace Cngp
{
	/// <summary>
	/// CngpProtocol 协议实现	
	/// </summary>
	[LastModified("2006-01-12","修改从数据库取数据的方法,指定时间限制")]
	[LastModified("2006-01-18","更改发送方法,先锁定,后检查有无发送信息,发送采用倒序")]
	[LastModified("2006-03-13","修改接收deliver信息的方法,停止while内的do while loop")]
	[LastModified("2006-03-14","mt,mo记录使用事件,做界面显示方法")]
	[LastModified("2007-02-26","修改Cngp_Deliver_Resp,增加写入状态报告的方法")]
	[LastModified("2007-04-03","修改DealSubResp和Cngp_Deliver_Resp,增加处理MsgId的方法")]
	internal class CngpProtocol
	{
		public delegate void MtChangeHandler(object sender,MtchangeEventArgs e);
		public static event MtChangeHandler MtOnChange;
		public static event MtChangeHandler MoOnChange;
		//--------------------------------------------------------------------
		/// <summary>
		/// cngpsocket 类实例
		/// </summary>
		private CngpSocket cngpSocket=new CngpSocket();
		private CngpMessage cngpMessage=new CngpMessage();
		private CngpSendMessage cngpSendMessage=new CngpSendMessage();
		/// <summary>
		/// 发送信息序列号
		/// </summary>
		public  static uint Sequence=0;
		/// <summary>
		/// 标示,是否同网关连接
		/// </summary>
		public  bool IsConnectedWithIsmg=false;
		
		/// <summary>
		/// 存储Thread的ArrayList
		/// </summary>
		private ArrayList ThreadArray=new ArrayList(13);			
		/// <summary>
		/// 接收的Mo的数量
		/// </summary>
		private  static uint MOCount=0;										
		/// <summary>
		/// 侦听网关请求的进程
		/// </summary>
		private Thread threadListen;										

		/// <summary>
		/// Submit后的信息放入的Array,Submit后的信息并不能保证送给了用户
		/// 需要从网关收到确认信息
		/// </summary>
		public  static ArrayList submitArray=new ArrayList(19);			
		/// <summary>
		/// 准备发送信息Array,存储从数据库中取出的信息
		/// </summary>
		public  static ArrayList readytoSendArray=new ArrayList(101);		

		/// <summary>
		/// 发送Mt的数量
		/// </summary>
		private  static uint MtCount=0;	
		/// <summary>
		/// 同网关的最后通讯时间
		/// </summary>							
		private DateTime LastTalk=DateTime.MinValue;	
		/// <summary>
		/// 发送数据的Timer
		/// </summary>			
		private System.Timers.Timer timerSendData=new System.Timers.Timer();
		/// <summary>
		/// 从网关收到的信息,标示是否可以继续发送
		/// </summary>
		public static bool FeebackOk=true;
		/// <summary>
		/// 标记已经休眠的时间
		/// </summary>
		private  DateTime SleepTime=DateTime.Now;	
		/// <summary>
		/// 全局退出标志
		/// </summary>
		public static bool quitFlag=false;			

		private OraData oradata=new OraData();

	

		/// <summary>
		/// 短消息子类型		
		/// </summary>
		public enum SubType
		{
			Cancel=0,   //取消订阅
			Request=1,  //订阅或者点播请求
			MODeliver=2,//点播下发
			MTDeliver=3 //订阅下发
		
		}
		/// <summary>
		/// 是否要求返回状态报告	
		/// </summary>
		public enum NeedReport:byte
		{
			Need=1,    //要求状态报告
			NotNeed=0  //不要求状态报告
		}
		/// <summary>
		/// 发送优先级
		/// </summary>
		public enum Priority:byte
		{
			Low=0,       //最低
			Normal=1,    //正常
			High=2,      //高
			Emegency=3   //最高
		}
		/// <summary>
		/// 资费类型
		/// </summary>
		public enum FeeType:byte
		{
			Free=0,     //免费
			MO=1,		//按条收费
			MT=2,		//包月
			Top=3,		//封顶
			MtFee=4,	//包月请求扣费
			CR=5		//cr话单
		
		}
		/// <summary>
		/// 计费用户类型
		/// </summary>		
		public enum FeeUserType:byte
		{
			Dest=0,    //对目的终端计费
			Source=1,  //对源终端计费
			SP=2,	   //对sp计费
			FeeMobile=3//按照计费用户号码计费
		}
		/// <summary>
		/// 信息头的Command_Status值
		/// </summary>
		public enum Command_Status:uint
		{
			Success=0,                //成功
			SystemBusy=1,			//系统忙
			OverMaxConnection=2,	//超过最大连接数
			MessageStructError=10,	//消息结构错
			CommandError=11,		//命令字错
			SequenceDouble=12,		//序列号重复
			IPAddressError=20,		//ip地址错
			AuthenError=21,			//认证错
			VersionTooHigh=22,		//版本太高
			InvalidFeeUserType=23,	//非法FeeUserType
			InvalidSubType=24,		//非法SubType
			OverNodesCount=25,		//NodesCount超过阙值
			InvalidMsgID=26,		//非法msgId
			InvalidSMType=30,		//非法smtype
			InvalidPriority=31,		//非法优先级 
			InvalidFeeType=32,		//非法Feetype
			InvalidFeeCode=33,		//非法FeeCode
			InvalidMsgFormat=34,	//非法MsgFormat
			InvalidTimeFormat=35,	//非法时间格式
			InvalidMsgLength=36,	//非法消息长度
			Expire=37,				//有效期已过
			InvalidQueryType=38,	//非法查询类别
			NoRoute=39,				//路由错误
			NoMobileId=40,			//帐户不存在
			NoYuE=41,				//余额不足
			InvalidMobile=42,		//帐户不可用
			NoPrePayUser=43			//非预付费用户

		}
		/// <summary>
		/// 属性,只读,返回最后通话时间
		/// </summary>
		public DateTime LastTime
		{
			get{return LastTalk;}
		}
		/// <summary>
		/// 构造函数 ,初始化自定义变量
		/// </summary>
		public CngpProtocol()
		{
			InitializeCompnent();
		}
		/// <summary>
		/// 初始化信息发送timer,设置timer的事件
		/// </summary>
		private void InitializeCompnent()
		{
			//
			//发送数据Timer,设定参数
			//
			timerSendData.Interval=Convert.ToInt32(ConfigInformation.Sendspeed);
			timerSendData.Elapsed+=new ElapsedEventHandler(timerSendData_Elapsed);
			timerSendData.Enabled=false;

		}

		/// <summary>
		/// Connect方法
		/// 如果成功,启动发送进程,接收进程
		/// </summary>
		/// <param name="user">网关设置的用户名</param>
		/// <param name="password">网关设置的密码</param>
		/// <param name="ipAddr" >网关IP地址</param>
		/// <param name="port" >网关端口</param>
		[LastModified("2006-03-13","Connect网关的方法")]
		public bool Cngp_Login(string user,string password,string ipAddr,int port)
		{
			//Socket Connect
			cngpSocket.Init(ipAddr,port);
			//-----------------------------------Authentication-----------------
			//authen数组
			byte[] bsAuthen=new byte[17+password.Length+user.Length];
			//当前时间,格式化为时间戳			
			string timeStamp=string.Concat(new string[]{
														   DateTime.Now.Month.ToString("00"),
														   DateTime.Now.Day.ToString("00"),
														   DateTime.Now.Hour.ToString("00"),
														   DateTime.Now.Minute.ToString("00"),
														   DateTime.Now.Second.ToString("00")});
			//7字节的0
			byte[] SevenZero=new byte[7];
			int i=0;//cursor
			cngpMessage.AddToBuffer(ref bsAuthen,ref i,user,user.Length,CngpMessage.Character.ASCII);
			cngpMessage.AddToBuffer(ref bsAuthen,ref i,SevenZero);
			cngpMessage.AddToBuffer(ref bsAuthen,ref i,password,password.Length,CngpMessage.Character.ASCII);
			cngpMessage.AddToBuffer(ref bsAuthen,ref i,timeStamp,10,CngpMessage.Character.ASCII);
			//md5
			byte[] Authen=cngpMessage.MD5CryptoGraphy(bsAuthen);
			//------------------------------------------------------------------------
			//-----------------------------body----------------------------------------
			byte[] MessageBody=new byte[32];
			byte Version=32;
			byte LoginMode=2;
			int j=0;//cursor
			cngpMessage.AddToBuffer(ref MessageBody,ref j,user,10,CngpMessage.Character.ASCII);
			cngpMessage.AddToBuffer(ref MessageBody,ref j,Authen);
			cngpMessage.AddToBuffer(ref MessageBody,ref j,LoginMode);
			cngpMessage.AddToBuffer(ref MessageBody,ref j,int.Parse(timeStamp));
			cngpMessage.AddToBuffer(ref MessageBody,ref j,Version);
			//---------------------------------------------------------------------------
			//----------------Pack-----------------------------------------------------
			uint Command=(uint)CngpMessage.Command_Id.login;
			byte[] Message=null;
			uint CommandStatus=0;
			cngpMessage.Pack(Command,CommandStatus,sequence(),MessageBody,ref Message);
			//send
			int sendbytes=cngpSocket.SendToIsmg(Message);
			//receive
			byte[] PartMessage=null;
			uint Length=0;
			uint receivebytes=cngpSocket.ReceiveFromIsmg(ref PartMessage,ref Length);
			uint reCommandId=0;
			uint reSequence=0;
			uint reCommand_Status=0;
			byte[] reMessageBody=null;
			cngpMessage.UnPack(Length,ref reCommandId,ref reCommand_Status,ref reSequence,ref reMessageBody,PartMessage);
			
#if DEBUG
			Logs.writeLog("commandstatus:"+reCommand_Status.ToString());
#endif
			//--------------------------------------------------------------------------------
			//如果验证成功,标记连接成功,记录日志
			if(reCommandId==(uint)CngpMessage.Command_Id.login_resp && reCommand_Status==0)
			{
				
				//Mark连接标记
				IsConnectedWithIsmg=true;		
				//lastTalk
				this.RenewTime();

				//
				//启动发送时钟
				//
				timerSendData.Start();		

				//
				//启动接收进程
				//
				threadListen=new Thread(new ThreadStart(ReceiveData));
				threadListen.Start();
				ThreadArray.Add(threadListen);


				//返回
				return true;
			}
			else
			{
				return false;
			}

		}
	
		/// <summary>
		/// 发送数据的timerSendData的方法
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		[LastModified("2006-01-18","Lock发送对列后,再检查有没有发送信息,保证一致性,"+
			 "发送为倒序发送")]
		private void timerSendData_Elapsed(object sender,ElapsedEventArgs e)
		{

			try
			{			
				//
				//如果信息集合中的信息数小于100,那么发送信息
				//采用倒序,发送信息
				//发送信息完成后,设置发送参数,加入提交Array
				//先锁定readytoSendArray,再检查有没有需要发送的信息
				//保证一致性
				//
				SendInfo sendInfo=null;
				uint Sequence=0;
				lock(readytoSendArray)
				{
					if(submitArray.Count<100 && readytoSendArray.Count>0)
					{
						sendInfo=(SendInfo)readytoSendArray[readytoSendArray.Count-1];
				
						//发送结构的值
						SendStruct(sendInfo,ref Sequence);
						//从Array中删除
						readytoSendArray.RemoveAt(readytoSendArray.Count-1);
					}

				}

				if(sendInfo!=null)
				{
					//设置发送参数,加入提交Array
					sendInfo.Times=1;
					sendInfo.DealTime=DateTime.Now;
					sendInfo.Sequence=Sequence;
					lock(submitArray)
					{
						submitArray.Add(sendInfo);
					}	
				}
				
				
			}
			catch(Exception ex)
			{
				Logs.writeLog(string.Concat(
					ex.Message,
					"\r\n",
					ex.StackTrace,
					"\r\n",
					ex.TargetSite.ToString(),
					"\r\n",
					ex.Source),false);
			}
		
			
		}
		/// <summary>
		/// 如果在已经Submit的信息Array中还存在没有收到回复的信息,
		/// 那么根据设置的等待时间和发送次数,再次Submit
		/// </summary>
		[LastModified("2005-12-19","根据设置的等待时间和发送次数,重发信息函数")]
		[LastModified("2006-01-06","此方法由Represend Class调用,while循环被终止时,"
			 +"报错误,一直没有解决")]
		[LastModified("2006-03-13","使用全局变量退出循环")]
		public void CheckSubmit()
		{
			while(true)
			{
				try
				{
					//
					//如果全局退出标志为true,那么停止循环
					//
					if(quitFlag==true)
					{
						break;
					}
					//
					//
					//
					lock(submitArray)
					{

						if(submitArray.Count>0)
						{
	
							for(int i=submitArray.Count-1;i>=0;i--)
							{
								//在提交Array中的信息
								SendInfo sendinfo=(SendInfo)submitArray[i];
								//时间间隔
								TimeSpan span=DateTime.Now-sendinfo.DealTime;
								
								if( sendinfo.Times<2 && span.TotalSeconds>10)
								{
									SendStruct(sendinfo);						//重新发送
									sendinfo.Times++;								//更新发送次数
									sendinfo.DealTime=DateTime.Now;					//更新发送时间
									Logs.writeLog(sendinfo.Mobileid,"resend");		//记录日志
						
								}
								else if(sendinfo.Times>=2)
								{
									submitArray.Remove(sendinfo);
									Logs.writeLog(sendinfo.Mobileid.Trim()+":"+sendinfo.ServiceId.Trim()+":"+sendinfo.Content.Trim(),false);
									//
									//发送失败信息写入数据库
									//2007-02-26

⌨️ 快捷键说明

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