package com.zy.common.HslCommunication.Enthernet.ComplexNet; import com.zy.common.HslCommunication.Core.Net.HslProtocol; import com.zy.common.HslCommunication.Core.Net.NetHandle; import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkXBase; import com.zy.common.HslCommunication.Core.Net.StateOne.AppSession; import com.zy.common.HslCommunication.Core.Types.*; import com.zy.common.HslCommunication.Utilities; import java.net.Socket; import java.util.Date; /** * 一个基于异步高性能的客户端网络类,支持主动接收服务器的消息 */ public class NetComplexClient extends NetworkXBase { /** * 实例化一个对象 */ public NetComplexClient() { session = new AppSession(); ServerTime = new Date(); } private AppSession session; // 客户端的核心连接对象 private int isConnecting = 0; // 指示客户端是否处于连接服务器中,0代表未连接,1代表连接中 private boolean IsQuie = false; // 指示系统是否准备退出 private Thread thread_heart_check = null; // 心跳线程 private String ipAddress = ""; // Ip地址 private int port = 1000; // 端口号 private boolean IsClientStart = false; // 客户端是否启动 private int ConnectFailedCount = 0; // 失败重连次数 private String ClientAlias = ""; // 客户端的别名 private Date ServerTime = new Date(); // 服务器的时间,暂时不支持使用 private int DelayTime = 0; // 获取延迟的时间 /** * 获取IP地址 * * @return Ip地址 */ public String getIpAddress() { return ipAddress; } /** * 设置Ip地址 * * @param ipAddress Ip地址 */ public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } /** * 获取端口号 * * @return 端口号 */ public int getPort() { return port; } /** * 设置端口号 * * @param port */ public void setPort(int port) { this.port = port; } /** * 获取客户端是否启动 * * @return boolean值 */ public boolean getIsClientStart() { return IsClientStart; } /** * 设置客户端是否启动 * * @param clientStart 客户端是否启动 */ public void setClientStart(boolean clientStart) { IsClientStart = clientStart; } /** * 获取失败重连次数 * * @return */ public int getConnectFailedCount() { return ConnectFailedCount; } /** * 获取客户端的登录标识名 * * @return 字符串信息 */ public String getClientAlias() { return ClientAlias; } /** * 设置客户端的登录标识名 * * @param clientAlias */ public void setClientAlias(String clientAlias) { ClientAlias = clientAlias; } /** * 获取服务器的时间 * @return */ // public Date getServerTime() { // return ServerTime; // } /** * 获取信息延迟的时间 * * @return */ public int getDelayTime() { return DelayTime; } /** * 客户端启动成功的事件,重连成功也将触发此事件,参数没有意义 */ public ActionOperate LoginSuccess; /** * 连接失败时触发的事件,参数为连接失败的次数 */ public ActionOperateExOne LoginFailed; /** * 服务器的异常,启动,等等一般消息产生的时候,出发此事件 */ public ActionOperateExOne MessageAlerts; /** * 在客户端断开后并在重连服务器之前触发,用于清理系统资源,参数无意义 */ public ActionOperate BeforReConnected; /** * 当接收到文本数据的时候,触发此事件 */ public ActionOperateExThree AcceptString; /** * 当接收到字节数据的时候,触发此事件 */ public ActionOperateExThree AcceptByte; /** * 关闭该客户端引擎 */ public void ClientClose() { IsQuie = true; if (IsClientStart) SendBytes(session, HslProtocol.CommandBytes(HslProtocol.ProtocolClientQuit, 0, Token, null)); IsClientStart = false; // 关闭客户端 thread_heart_check = null; LoginSuccess = null; // 清空所有的事件 LoginFailed = null; MessageAlerts = null; AcceptByte = null; AcceptString = null; try { session.getWorkSocket().close(); } catch (Exception ex) { } if (LogNet != null) LogNet.WriteDebug(toString(), "Client Close."); } /** * 启动客户端引擎,连接服务器系统 */ public void ClientStart() { // 如果处于连接中就退出 if (isConnecting != 0) return; isConnecting = 1; // 启动后台线程连接 new Thread(){ @Override public void run() { ThreadLogin(); } }.start(); // 启动心跳线程,在第一次Start的时候 if (thread_heart_check == null) { thread_heart_check = new Thread(){ @Override public void run() { ThreadHeartCheck(); } }; thread_heart_check.start(); } } /** * 连接服务器之前的消息提示,如果是重连的话,就提示10秒等待信息 */ private void AwaitToConnect() { if (ConnectFailedCount == 0) { // English Version : Connecting Server... if (MessageAlerts != null) MessageAlerts.Action("正在连接服务器..."); } else { int count = 10; while (count > 0) { if (IsQuie) return; count--; // English Version : Disconnected, wait [count] second to restart if (MessageAlerts != null) MessageAlerts.Action("连接断开,等待" + count + "秒后重新连接"); try { Thread.sleep(1000); } catch (Exception ex) { } } if (MessageAlerts != null) MessageAlerts.Action("正在尝试第" + ConnectFailedCount + "次连接服务器..."); } } private void ConnectFailed() { ConnectFailedCount++; isConnecting = 0; if (LoginFailed != null) LoginFailed.Action(ConnectFailedCount); if (LogNet != null) LogNet.WriteDebug(toString(), "Connected Failed, Times: " + ConnectFailedCount); } private OperateResultExOne ConnectServer() { OperateResultExOne connectResult = CreateSocketAndConnect(ipAddress, port, 10000); if (!connectResult.IsSuccess) { return connectResult; } // 连接成功,发送数据信息 OperateResult sendResult = SendStringAndCheckReceive(connectResult.Content, 2, ClientAlias); if (!sendResult.IsSuccess) { return OperateResultExOne.CreateFailedResult(sendResult); } if (MessageAlerts != null) MessageAlerts.Action("连接服务器成功!"); return connectResult; } private void LoginSuccessMethod(Socket socket) { ConnectFailedCount = 0; try { session.setIpEndPoint(socket.getInetAddress()); session.setLoginAlias(ClientAlias); session.setWorkSocket(socket); session.setHeartTime(new Date()); IsClientStart = true; BeginReceiveBackground(session); } catch (Exception ex) { if (LogNet != null) LogNet.WriteException(toString(), ex); } } private void ThreadLogin() { // 连接的消息等待 AwaitToConnect(); OperateResultExOne connectResult = ConnectServer(); if (!connectResult.IsSuccess) { ConnectFailed(); // 连接失败,重新连接服务器 new Thread(){ @Override public void run() { ReconnectServer(null); } }.start(); return; } // 登录成功 LoginSuccessMethod(connectResult.Content); // 登录成功 if (LoginSuccess != null) LoginSuccess.Action(); isConnecting = 0; try { Thread.sleep(200); } catch (Exception ex) { } } private void ReconnectServer(Object obj) { // 是否连接服务器中,已经在连接的话,则不再连接 if (isConnecting == 1) return; // 是否退出了系统,退出则不再重连 if (IsQuie) return; // 触发连接失败,重连系统前错误 if (BeforReConnected != null) BeforReConnected.Action(); if (session != null) { CloseSocket(session.getWorkSocket()); } // 重新启动客户端 ClientStart(); } /** * 通信出错后的处理 * * @param receive 通信方法 */ @Override protected void SocketReceiveException(AppSession receive) { if (LogNet != null) LogNet.WriteDebug(toString(), "Socket Excepiton Occured."); // 异常掉线 ReconnectServer(null); } /** * 服务器端用于数据发送文本的方法 * * @param customer 用户自定义的命令头 * @param str 发送的文本 */ public void Send(NetHandle customer, String str) { if (IsClientStart) { SendBytes(session, HslProtocol.CommandBytes(customer.get_CodeValue(), Token, str)); } } /** * 服务器端用于发送字节的方法 * * @param customer 用户自定义的命令头 * @param bytes 实际发送的数据 */ public void Send(NetHandle customer, byte[] bytes) { if (IsClientStart) { SendBytes(session, HslProtocol.CommandBytes(customer.get_CodeValue(), Token, bytes)); } } private void SendBytes(AppSession stateone, byte[] content) { super.Send(stateone.getWorkSocket(), content); } /** * 客户端的数据处理中心 * * @param session 连接状态 * @param protocol 协议头 * @param customer 用户自定义 * @param content 数据内容 */ @Override protected void DataProcessingCenter(AppSession session, int protocol, int customer, byte[] content) { if (protocol == HslProtocol.ProtocolCheckSecends) { Date dt = new Date(Utilities.getLong(content, 0)); ServerTime = new Date(Utilities.getLong(content, 8)); DelayTime = (int) (new Date().getTime() - dt.getTime()); this.session.setHeartTime(new Date()); // MessageAlerts?.Invoke("心跳时间:" + DateTime.Now.ToString()); } else if (protocol == HslProtocol.ProtocolClientQuit) { // 申请了退出 } else if (protocol == HslProtocol.ProtocolUserBytes) { // 接收到字节数据 if (AcceptByte != null) AcceptByte.Action(this, new NetHandle(customer), content); } else if (protocol == HslProtocol.ProtocolUserString) { // 接收到文本数据 String str = Utilities.byte2String(content); if (AcceptString != null) AcceptString.Action(this, new NetHandle(customer), str); } } /** * 心跳线程的方法 */ private void ThreadHeartCheck() { try { Thread.sleep(2000); } catch (Exception ex) { } while (true) { try { Thread.sleep(1000); } catch (Exception ex) { } if (!IsQuie) { byte[] send = new byte[16]; byte[] buffer = Utilities.getBytes(new Date().getTime()); System.arraycopy(buffer, 0, send, 0, buffer.length); try { SendBytes(session, HslProtocol.CommandBytes(HslProtocol.ProtocolCheckSecends, 0, Token, send)); double timeSpan = (new Date().getTime() - session.getHeartTime().getTime()) / 1000; if (timeSpan > 1 * 8)//8次没有收到失去联系 { if (isConnecting == 0) { if (LogNet != null) LogNet.WriteDebug(toString(), "Heart Check Failed int " + timeSpan + " Seconds."); new Thread(){ @Override public void run() { ReconnectServer(null); } }.start(); } if (!IsQuie) { try { Thread.sleep(1000); } catch (Exception ex) { } } } } catch (Exception ex) { System.out.println(ex.getStackTrace()); } } else { break; } } } /** * 返回对象的字符串表示形式 * * @return 字符串 */ @Override public String toString() { return "NetComplexClient"; } }