当我们用Netty实现一个TCP client时,我们当然希望当连接断掉的时候Netty能够自动重连。
Netty Client有两种情况下需要重连:
- Netty Client启动的时候需要重连
- 在程序运行中连接断掉需要重连。
对于第一种情况,Netty的作者在stackoverflow上给出了解决方案,
对于第二种情况,Netty的例子uptime中实现了一种解决方案。
而Thomas在他的文章中提供了这两种方式的实现的例子。
实现ChannelFutureListener 用来启动时监测是否连接成功,不成功的话重试:
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
|
public
class
Client
{
private
EventLoopGroup loop =
new
NioEventLoopGroup();
public
static
void
main( String[] args )
{
new
Client().run();
}
public
Bootstrap createBootstrap(Bootstrap bootstrap, EventLoopGroup eventLoop) {
if
(bootstrap !=
null
) {
final
MyInboundHandler handler =
new
MyInboundHandler(
this
);
bootstrap.group(eventLoop);
bootstrap.channel(NioSocketChannel.
class
);
bootstrap.option(ChannelOption.SO_KEEPALIVE,
true
);
bootstrap.handler(
new
ChannelInitializer<SocketChannel>() {
@Override
protected
void
initChannel(SocketChannel socketChannel)
throws
Exception {
socketChannel.pipeline().addLast(handler);
}
});
bootstrap.remoteAddress(
"localhost"
,
8888
);
bootstrap.connect().addListener(
new
ConnectionListener(
this
));
}
return
bootstrap;
}
public
void
run() {
createBootstrap(
new
Bootstrap(), loop);
}
}
|
ConnectionListener 负责重连:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
class
ConnectionListener
implements
ChannelFutureListener {
private
Client client;
public
ConnectionListener(Client client) {
this
.client = client;
}
@Override
public
void
operationComplete(ChannelFuture channelFuture)
throws
Exception {
if
(!channelFuture.isSuccess()) {
System.out.println(
"Reconnect"
);
final
EventLoop loop = channelFuture.channel().eventLoop();
loop.schedule(
new
Runnable() {
@Override
public
void
run() {
client.createBootstrap(
new
Bootstrap(), loop);
}
}, 1L, TimeUnit.SECONDS);
}
}
}
|
同样在ChannelHandler监测连接是否断掉,断掉的话也要重连:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
MyInboundHandler
extends
SimpleChannelInboundHandler {
private
Client client;
public
MyInboundHandler(Client client) {
this
.client = client;
}
@Override
public
void
channelInactive(ChannelHandlerContext ctx)
throws
Exception {
final
EventLoop eventLoop = ctx.channel().eventLoop();
eventLoop.schedule(
new
Runnable() {
@Override
public
void
run() {
client.createBootstrap(
new
Bootstrap(), eventLoop);
}
}, 1L, TimeUnit.SECONDS);
super
.channelInactive(ctx);
}
}
|
参考文档
- http://stackoverflow.com/questions/19739054/whats-the-best-way-to-reconnect-after-connection-closed-in-netty
- https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/uptime/UptimeClientHandler.java
- http://tterm.blogspot.jp/2014/03/netty-tcp-client-with-reconnect-handling.html
- ctx.close vs ctx.channel().close
- ctx.write vs ctx.channel().write