一、客户端代码存在的必要性以及我认为需要解决的问题
就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();
}
}
}
}
来源:oschina
链接:https://my.oschina.net/u/2397619/blog/498644