Netty4客户端断线重连机制

首先要了解一下Netty4客户端的运行机制,NettyClient.java代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class NettyClient {
    private final String host;
    private final int port;

    public NettyClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void run() throws Exception {
        // Configure the client.
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .option(ChannelOption.TCP_NODELAY, true)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(
                             //new LoggingHandler(LogLevel.INFO),
                             new NettyHandler());
                 }
             });

            // Start the client.
            ChannelFuture f = b.connect(host, port).sync();

            // Wait until the connection is closed.
            f.channel().closeFuture().sync();//运行后会在这里阻塞
        } finally {
            // Shut down the event loop to terminate all threads.
            group.shutdownGracefully();
        }
    }
}

当我们在主线程中执行 NettyClient(NettyClient).run()时,主线程会在 ChannelFuture f = b.connect(host, port).sync(); 这里阻塞,这是Netty4的一个新特性,我们利用这个特性即可创建一个定时器来实现断线重连的功能。

定时器的代码如下ReconnectTimer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 断线重连定时器
*
* @author BeiTown
* @date 2014-5-16
*/

public class ReconnectTimer extends TimerTask {
    @Override
    public void run() {
        System.out.println("正在尝试与服务器连接......");
        try {
            new GameClient("192.168.0.146", 10046).run();
            System.out.println("与服务器断开连接,尝试10秒后与服务器重新连接......");
        } catch (Exception e) {
            System.out.println("无法连接到服务器,尝试10秒后与服务器重新连接......");
            return;
        }
    }
}

当执行定时器时,定时器走到 new GameClient(“192.168.0.116″, 22222).run() 这里就会被阻塞,直到断开连接后才会继续执行后续的代码。
这里如果不捕获 new GameClient(“192.168.0.146″, 10046).run() 的异常的话会照成整个计时器的异常并终止计时器,因此需要加上 try catch 进行包裹。
最后,在Main函数中启动这个定时器即可:

1
2
3
4
public static void main(String[] args) throws Exception {
    Timer clientTimer = new Timer("Client Reconnect Timer");// 创建定时器
    clientTimer.schedule(new ReconnectTimer(), 0, 10 * 1000);// 开启断线重连定时器
}

这里稍微提一下schedule这个方法,之前测试时基于用了习惯用了scheduleAtFixedRate方法,这是基于时间修正的一个定时器方法,但在定时器长期阻塞之后,程序为了修正时间,保证平均10s执行一次的频率,在后续动作中疯狂的赶时间执行命令,因此不适合本方案,故更正为schedule这个方法,即不再基于时间修正,保证阻塞结束之后,按照每10s一次的频率执行run()中的内容。

测试:
在服务器开启之前运行客户端,打印如下

正在尝试与服务器连接......
无法连接到服务器,尝试10秒后与服务器重新连接......
正在尝试与服务器连接......
与服务器连接成功......

关闭服务器后打印如下

与服务器断开连接,尝试10秒后与服务器重新连接......
正在尝试与服务器连接......
无法连接到服务器,尝试10秒后与服务器重新连接......
正在尝试与服务器连接......

到此一个基于Netty客户端的断线重连机制就已实现完毕,如果有其他优化方案欢迎大家交流讨论。
本篇到此,谢谢关注。

BeiTown
2014-05-16

本文链接:Netty4客户端断线重连机制

转载声明:BeiTown原创,转载请注明来源:BeiTown's Coder 编码之源,谢谢


Tags: , , , ,