一、客户端代码存在的必要性以及我认为需要解决的问题
就NIO通讯本身而言完全没必要分开,其实客户端代码和服务端代码可以放到一起。但是在业务上是分开的。我在做nio的时候思考了许多我自己认为应该解决的问题;主要的如下:
1、链路维护(心跳);
定期的向服务端发送维持链路报文,获得服务端的响应,以证明其仍然在存活状态;同时服务端会记录客户端每次维持链路的时间,用于服务端对通道的超时 判断;
2、断线重连:
一种情况是正常断线,目前我利用对channel的read返回来进行判断;
另一种是非正常短线,我利用维持链路的心跳回应来进行判断,也就是说,当连续发送固定次数的维持链路指令,没有收到服务端的回应的时候,主动断线,启动重连;
二、具体实现:
1、链路维护代码:
- 定时发送维持链路指令;
- 判断维持链路指令缓冲区(此缓冲区在每次发送维持链路指令的时候会将指令记录到缓冲区,每次收到链路维护回应报文的时候,会将其所对应的指令清除,如果连续多次收不到回应,那么缓冲区的大小就会达到设置的阈值)的大小,如果达到预设值,就设置客户端连接状态为false;重连线程会依据这个标记做是否重连的判断。
public class KeepChannelThread extends Thread { private static Logger logger = LogManager.getLogger(KeepChannelThread.class.getName()); private int reconnectTag = 0; public void run(){ while(true){ //构建链路维护指令对象 ClientKeepOrder keepOrder = (ClientKeepOrder)Client.getOrderInstance(ClientKeepOrder.HEADER); keepOrder.initClientKeepOrder(); if (StringUtils.isBlank(keepOrder.getToken())){ logger.info("未收到服务端分配的身份标识,暂不发送链路维护报文!"); reconnectTag++; if (reconnectTag>Client.getKeepTimeoutCount()){ Client.clearToken4Disconnect(); } }else { reconnectTag = 0; try { //触发重连机制 if (Client.KEEP_ORDER_MAP.size()>=Client.getKeepTimeoutCount()){ Client.clearToken4Disconnect(); logger.info("维持链路发现服务端未响应数量达到阈值,进行重连操作!"); continue; } //发送链路维持报文 Client.write2Channel(keepOrder); //保存链路维持报文到缓冲区,等待服务端回应清除。 ClientKeepOrder keepOrderValue = new ClientKeepOrder(); keepOrderValue = keepOrder; Client.KEEP_ORDER_MAP.put(keepOrder.getRid(), keepOrderValue); } catch (IOException e) { e.printStackTrace(); continue; } } try { Thread.sleep(Client.getKeepAliveCycle()*1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
时间: 2024-11-05 21:43:25