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

📄 connectionbean.java

📁 JAVA做的短信平台
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.ll.smsbeans;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Logger;

import com.ll.smsbeans.cmpp3.CmppActiveTestBuilder;
import com.ll.smsbeans.cmpp3.CmppActiveTestRespBuilder;
import com.ll.smsbeans.cmpp3.CmppConnectBuilder;
import com.ll.smsbeans.cmpp3.CmppConnectResp;
import com.ll.smsbeans.cmpp3.CmppPacket;
import com.ll.smsbeans.cmpp3.CmppPacketCommon;
import com.ll.smsbeans.cmpp3.CmppTerminateBuilder;
import com.ll.smsbeans.cmpp3.CmppTerminateRespBuilder;
import com.ll.smsbeans.log.LogCommon;

/**
 * ConnectionBean 是smsbeans中主要的bean.
 * <p>
 * ConnectionBean 主要是和服务器建立认证连接,所有其它的bean都是通过它和服务器通信的。
 * <p>
 * ConnectionBean提供一些“标准”的于服务器通信的接口,例如send方法,同时在内部自动处理一些服务
 * 器端的消息的回服例如ActiveTest等,并且,在运行过程中处理数据包的发送失败,保持链路联结。
 * <p>
 * 所有其它的beans通过ConnectionBean发送数据,和通过监听由ConnectionBean发布的received消息接收过滤数据
 
 * <p>
 * @see MessengerBean
 * @see IQBean
 * @see RosterBean
 * 
 
 *
 * @author  listlike <a href="mailto:listlike@hotmail.com">
 *                      <i>&lt;listlike@hotmail.com&gt;</i></a>
 
 * @version $Revision: 1.0 $
 */
public class ConnectionBean implements Serializable, PacketListenerRegistrar
{
	/**
	*
	* Timer为定时器类
	* 为ConnectBean提供定时服务,通过定时调用 主要用于回复包的时间记数,以及保持链路测试包的定时发送。 
	* 有两个定时器:
	* 1 秒定时器	
	* 	用于回复包的时间记数,每秒激活一次ConnectionBean.onTimer.
	* 2 保持链路测试包定时器
	* 	用于保持链路测试包的记时,根据常数ACTIVETIME的值激活ConnectBeantion.onActiveConnect。
	* 
	* @see com.ll.smsbeans.ConnectionBean#onTimer()
	* @see ConnectionBean#onActiveConnect()
	* @see ConnectionBean#ACTIVETIME
	*<p>
	* @author  listlike <a href="mailto:listlike@hotmail.com">
	*                      <i>&lt;listlike@hotmail.com&gt;</i></a>
	*
	 */
	public class Timer extends Thread
	{
		// 保持链路测试包的记时
		private long activeSec = 0;
		//定时器是否有效
		private boolean enableTimer = true;
		//保持链路测试的定时器是否有效
		private boolean enableActiveTimer = true;

		private boolean timerRun = true;

		/**
		 * 保持链路测试的定时器复位
		 */
		public void resetActiveTime()
		{
			activeSec = System.currentTimeMillis();
		}

		/**
		* @see java.lang.Runnable#run()
		*/
		public void run()
		{

			while (timerRun)
			{
				try
				{
					sleep(1000);
					if (enableTimer)
						ConnectionBean.this.onTimer();

					if (System.currentTimeMillis() - activeSec
						>= ACTIVETIME * 1000)
					{
						resetActiveTime();
						if (enableActiveTimer)
							ConnectionBean.this.onActiveConnect();

					}
				} catch (InterruptedException e)
				{
					return;

				} catch (Exception e)
				{
					return;
				}
			}
		}

		/**
		 * 定时器状态
		 * @return 定时器状态
		 */
		public boolean isEnableActiveTimer()
		{
			return enableActiveTimer;
		}

		/**
		 * 保持链路测试的定时器状态
		 * @return 保持链路测试的定时器状态
		 */
		public boolean isEnableTimer()
		{
			return enableTimer;
		}

		/**
		 * 设置保持链路测试的定时器状态
		 * @param enable 设置保持链路测试的定时器状态
		 */
		public void setEnableActiveTimer(boolean enable)
		{
			enableActiveTimer = enable;
		}

		/**
		 * 设置定时器状态
		 * @param enable 设置定时器状态
		 */
		public void setEnableTimer(boolean enable)
		{
			enableTimer = enable;
		}

		/* (非 Javadoc)
		 * @see java.lang.Thread#interrupt()
		 */
		public void interrupt()
		{

			timerRun = false;
			super.interrupt();
		}

		/* (非 Javadoc)
		 * @see java.lang.Thread#start()
		 */
		public synchronized void start()
		{
			reset();
			super.start();
		}

		private void reset()
		{

			enableTimer = true;
			enableActiveTimer = true;
			timerRun = true;
			resetActiveTime();
		}

	}
	/**
	*PacketStreamMonitor 通过响应数据报发送和接收事件,维护ConnectionBean的连接。
	*  
	*
	* @author  listlike <a href="mailto:listlike@hotmail.com">
	*                      <i>&lt;listlike@hotmail.com&gt;</i></a>
	*
	 */
	public class PacketStreamMonitor implements PacketListener
	{

		/**
		 * 主要工作:
		 * 1、 将接收到的回复包从发送队列移出。
		 * 2、 判断是否登陆成功。
		 * 3、 自动处理中断包和中断回复包。
		 * 4、 处理链路测试包。  
		 * @see com.ll.smsbeans.PacketListener#receivedPacket(com.ll.smsbeans.PacketEvent)
		 */
		public void receivedPacket(PacketEvent pe)
		{
			_log.info(pe.getPacket().toString());

			if (((CmppPacket) pe.getPacket()).isResponse())
			{

				SendPacketState sps = sendPacketList.get(pe.getPacket());
				if (sps != null)
				{
					sps.setState(SendPacketState.STATE_RESPONSED);
					sps.setRespPacket(pe.getPacket());
				}
				//sendPacketList.remove( pe.getPacket());

			}

			if (status.getValue() == ConnectionEvent.EState.CONNECTING)
			{

				Packet p = pe.getPacket();
				if (p != null)
				{

					if (p instanceof CmppPacket)
					{
						CmppPacket cp = (CmppPacket) p;

						if (cp.getCommandId()
							== CmppPacketCommon.ID_CMPP_CONNECT_RESP)
							//  0x80000001
						{

							sendPacketList.remove(cp);
							CmppConnectResp ccr = (CmppConnectResp) cp;
							if (ccr.getStatus() == 0)
							{

								setConnectionState(
									ConnectionEvent.STATE_CONNECTED,
									ConnectionEvent.REASON_CLIENT_INITIATED);

								mTimer = new Timer();
								mTimer.start();

							} else
							{
								disconnected(
									ConnectionEvent.REASON_SERVER_INITIATED);
							}

						}
					}

				}

				return;

			}

			if (status.getValue() == ConnectionEvent.EState.CONNECTED)
			{
				Packet p = pe.getPacket();
				if (p != null)
				{
					if (p instanceof CmppPacket)
					{
						CmppPacket cp = (CmppPacket) p;
						switch (cp.getCommandId())
						{
							case CmppPacketCommon.ID_CMPP_TERMINATE_RESP :
								//0x80000002
								sendPacketList.remove(pe.getPacket());
								disconnected(
									ConnectionEvent.REASON_CLIENT_INITIATED);
								break;

							case CmppPacketCommon.ID_CMPP_TERMINATE :
								//0x00000002

								CmppTerminateRespBuilder ctrb =
									new CmppTerminateRespBuilder();
								ctrb.setSequenceId(cp.getSequenceId());
								send(ctrb.builder());

								break;
							case CmppPacketCommon.ID_CMPP_ACTIVE_TEST :
								//0x00000008

								CmppActiveTestRespBuilder catrb =
									new CmppActiveTestRespBuilder();
								catrb.setSequenceId(cp.getSequenceId());
								send(catrb.builder());
								mTimer.resetActiveTime();
								break;
							case CmppPacketCommon.ID_CMPP_ACTIVE_TEST_RESP :
								//0x80000008
								sendPacketList.remove(cp);
								break;
							default :
								break;
						}

					}

				}

			}

			_log.log(
				LogCommon.DEBUG_LEVEL,
				"sendPacketList=" + sendPacketList.size());
		}

		/**
		 * 主要工作:处理服务器端发送来的中断包。
		 *  
		 * @see com.ll.smsbeans.PacketListener#sentPacket(com.ll.smsbeans.PacketEvent)
		 */
		public void sentPacket(PacketEvent pe)
		{

			_log.info(pe.getPacket().toString());

			if (status.getValue() == ConnectionEvent.EState.CONNECTED)
			{
				Packet p = pe.getPacket();
				if (p != null)
				{
					if (p instanceof CmppPacket)
					{
						CmppPacket cp = (CmppPacket) p;

						if (cp.getCommandId()
							== CmppPacketCommon.ID_CMPP_TERMINATE_RESP)
							//0x80000002
							disconnected(
								ConnectionEvent.REASON_SERVER_INITIATED);
					}

				}

			}
		}

		/**
		 * 处理中断包发送失败
		 * @see com.ll.smsbeans.PacketListener#sendFailed(com.ll.smsbeans.PacketEvent)
		 */
		public void sendFailed(PacketEvent pe)
		{

			_log.info(pe.getPacket().toString());

			if (!((CmppPacket) pe.getPacket()).isResponse())
			{

				SendPacketState sps = sendPacketList.get(pe.getPacket());
				if (sps != null)
				{
					sps.setState(SendPacketState.STATE_FAILED);

				}
				//sendPacketList.remove( pe.getPacket());

			}

			if ((((CmppPacket) pe.getPacket()).getCommandId()
				== CmppPacketCommon.ID_CMPP_ACTIVE_TEST) // 0x00000008
				| (((CmppPacket) pe.getPacket()).getCommandId()
					== CmppPacketCommon.ID_CMPP_TERMINATE)) // 0x00000002
			{
				sendPacketList.remove(pe.getPacket());
				disconnected(ConnectionEvent.REASON_IO_ERROR);

			}
		}

	}

	/**
	 * 链路测试的时间间隔为3分钟(180秒)。
	 */
	public final static int ACTIVETIME = 30;

	/**
	 * 发送包的超时时间为60秒。
	 */
	public final static int OVERTIME = 10;
	/**
	 * 重复发包的次数
	 */
	private final static int RESENDCOUNT = 3;

	private String sourceAddr;
	private String password;

	private IdBuilder idBuilder;

	/**
	 * 定时器
	 */
	private Timer mTimer;

	/**
	 * 缓存没有接收到回复包的发送包,并且记录每个包的发包时间和发包次数
	 */
	private SendPackStateList sendPacketList = SendPackStateList.getInstance();

	/** 当前连接的状态*/
	private ConnectionEvent.EState status;

	/** 所有实现连接事件监听接口的对象列表 */
	private final Vector connectionListeners = new Vector();

	/** 所有实现数据包的对象列表 */
	private final Vector packetListeners = new Vector();

	/** 用于连接的Socket */
	private Socket socket = null;

	private InputStreamInterface isi = new InputStreamInterface();

	private OutputStreamInterface osi = new OutputStreamInterface();

	/** 输入数据流线程,用于解析数据包,并且发送接收数据包事件 */
	private InputStreamHandler input = null;

	/** 输出数据留线程,用于发送数据包,并且发送发送数据包事件 */
	private OutputStreamHandler output = null;

	/**
	 * 默认服务器端口
	 */
	private int DEFAULT_PORT = 7890;

	static Logger _log;

	/**
	*用于输出线程回调ConnectionBean的方法的接口类
	*  
	*
	* @author  listlike <a href="mailto:listlike@hotmail.com">
	*                      <i>&lt;listlike@hotmail.com&gt;</i></a>
	*
	 */
	public class OutputStreamInterface
	{
		public void sent(Packet p)
		{

			ConnectionBean.this.sent(p);
		}

		public void sendFailed(Packet p)
		{
			ConnectionBean.this.sendFailed(p);
		}

		public void unexpectedThreadDeath(Exception e)
		{
			ConnectionBean.this.onOutputDeath(e);
		}
	}

	/**
	*用于输入线程回调ConnectionBean的方法的接口类
	*  
	*
	* @author  listlike <a href="mailto:listlike@hotmail.com">
	*                      <i>&lt;listlike@hotmail.com&gt;</i></a>
	*
	 */

	public class InputStreamInterface
	{
		public void received(Packet p)
		{

			ConnectionBean.this.received(p);
		}

		public void unexpectedThreadDeath(Exception e)
		{
			ConnectionBean.this.onInputDeath(e);
		}
	}

	/**
	 * 构造函数
	 */
	public ConnectionBean(String sourceAddr, String password)
	{
		this.sourceAddr = sourceAddr;
		this.password = password;

		idBuilder = IdBuilder.getInstance();
		status = ConnectionEvent.STATE_DISCONNECTED;
		output = null;
		input = null;

⌨️ 快捷键说明

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