基于NIO的消息路由的实现(七)客户端的一些实现,维持链路,断线重连

一、客户端代码存在的必要性以及我认为需要解决的问题

就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

基于NIO的消息路由的实现(七)客户端的一些实现,维持链路,断线重连的相关文章

基于NIO的消息路由的实现(四) 服务端通讯主线程(1)

一.简单介绍: 服务端通讯主线程是消息路由服务的启动类,其主要作用如下: 1.初始化相关配置: 2.根据配置的ip和port创建tcp服务: 3.接收客户端连接,并给客户端分配令牌: 4.接收客户端的登录请求,并将客户端相关信息(令牌.客户端登录标识.最后访问时间.当前token所使用的通道,保存到缓冲区) 5.接收客户端的报文请求,并添加到通讯队列,等待处理: 6.接收来自各处的指令发送请求,并发送至相关通道: 二.详细介绍: 1.启动方法:首先加载配置信息:然后启动主线程.通讯报文消费线程(

基于NIO的消息路由的实现(四) 服务端通讯主线程(2)断包和粘包的处理

本来我打算单独开一章,专门说明粘包和断包,但是觉得这个事儿我在做的时候挺头疼的,但是对于别人或许不那么重要,于是就在这里写吧. 那么何谓粘包.何谓断包呢? 粘包:我们知道客户端在写入报文给服务端的时候,首先要将需要写入的内容写入Buffer,以ByteBuffer为例,如果你Buffer定义的足够大,并且你发送的报文足够快,此时就会产生粘包现象,举例来说 你发送一个 报文" M|A",然后你有发送了一个"M|B",如果产生粘包,服务端从缓冲区里面读出的就是"

基于NIO的消息路由的实现(三)服务端与客户端结构

一.服务器端结构: 如图所示: 指令类和报文类:对下行的指令和上行的报文进行了类的封装,分别实现IOrder和IPacket接口,继承Order,Packet基类: 服务主线程:接受客户端连接,将客户端发送的报文投递到通讯队列中,发送指令给客户端:保存连接对象(GVConnection) 通讯队列CQ:存储客户端发送过来的报文,此报文由通讯主线程放入: 通讯队列消费者:对通讯队列中的报文进行处理,该做什么做什么,如果是短消息,则放入消息队列MQ中单独处理: 消息队列消费者:对MQ中的短消息进行处

基于NIO的消息路由的实现(六)报文队列的处理

一.报文队列的处理: 如果将多路复用器获取到的所有事件,阻塞式的同步处理,那恐怕会严重影响selector的性能,所以我把从客户端接收到的大部分消息,都放入了队列中,然后另外启动队列的消费线程对消息进行异步的处理:具体如下: 1.通讯报文队列消费者:在selector对read事件的处理过程中,我在最后都把客户端发送的报文放入了一个叫CQUEUE的队列中,具体定义如下,CQUEUE是所有客户端发送报文的队列,在CQUEUE队列中的消费者线程中,我又对M类报文进行了对垒处理,放入了另一个队列MQU

基于NIO的服务器模型

最简单服务器模型是thread-per-connection,即每个客户端连接对于一个专属的工作线程,工作线程等待客户端发送数据.接收处理数据.返回响应数据然后继续等待新的数据的到来,这种模型能够保证很好的响应速度,但如果有大量并发连接会导致大量的工作线程,而且这些线程浪费了很多时间等待新数据,这些导致了这种服务器模型不适合高并发的情况. 如果服务器需要应对大量但可能并不实时活跃的连接,那么thread-on-event模型就比较适合.这种模型工作线程独立于客户端连接,只用来处理特定的事件,例如

Java基础知识强化之网络编程笔记24:Android网络通信之 AndroidAsync(基于nio的异步通信库)

1. AndroidAsync   AndroidAsync 是一个基于nio的异步socket ,http(客户端服务器端),websocket,socket.io库,AndroidAsync 是一个底层的网络协议库,如果你想要一个容易使用,高级的,http请求库,请使用Ion(它是基于AndroidAsync 的),正常来说开发者更倾向于使用  Ion. 如果你需要一个未被封装的Android的raw Socket, HTTP client/server, WebSocket, and So

开源一个基于nio的java网络程序

因为最近要从公司离职,害怕用nio写的网络程序没有人能看懂(或许是因为写的不好吧),就调整成了mina(这样大家接触起来非常方便,即使没有socket基础,用起来也不难),所以之前基于nio写的网络程序就开放出来好了! 写的比较挫,大家见谅! 首先是PollServer类,主要处理select,做网络事件的监听和基于FutureTask的数据发送,代码如下: package gs.gate; import gs.gate.handle.ClientHandle; import java.util

Android 基于Netty的消息推送方案之概念和工作原理(二)

上一篇文章中我讲述了关于消息推送的方案以及一个基于Netty实现的一个简单的Hello World.为了更好的理解Hello World中的代码,今天我来解说一下关于Netty中一些概念和工作原理的内容,假设你认为本篇文章有些枯燥.请先去阅读<Android 基于Netty的消息推送方案之Hello World(一)> ChannelEvent Netty是基于事件驱动的,就是我们上文提到的.发生什么事.就通知"有关部门". 所以.不难理解.我们自己的业务代码中,一定有跟这

[3.11] 扩展类库:基于FastRoute的快速路由

3.11.1 扩展类库:基于FastRoute的快速路由 此扩展基于 实现,需要 PHP 5.4.0 及以上版本,可以通过配置实现自定义路由配置,从而轻松映射到PhalApi中的service接口服务. 3.11.2 安装和配置 (1)扩展包下载 从  PhalApi-Library  扩展库中下载获取 FastRoute 七牛扩展包,如使用: git clone https://git.oschina.net/dogstar/PhalApi-Library.git 然后把 FastRoute