Reputation: 13
My netty IO client should keep trying to connect to a server whenever the server is restarted or the existing connection is broken. To implement this my client creates a new thread for establishing a new connection whenever the ChannelInActive callback method of my ChannelInboundHandlerAdapter is invoked. But my client throws the below error while establishing a new connection.
Exception in thread "main" io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /127.0.0.1:8888 at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source) at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:325) at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:633) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Unknown Source) Caused by: java.net.ConnectException: Connection refused: no further information ... 11 more
Below lines are the run part of my connection thread.
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class).handler(new
ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws
Exception {
socketChannel.pipeline().addLast(new
LengthFieldBasedFrameDecoder(64 * 1024, 0, 2));
socketChannel.pipeline().addLast(ClientHandler);
}
});
bootstrap.option(ChannelOption.SO_REUSEADDR,true);
ChannelFuture channelFuture=null;
try
{
channelFuture = bootstrap.connect(new InetSocketAddress(IP,
port)).sync();
channelFuture.awaitUninterruptibly();
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture)
{
try
{
if (channelFuture.isSuccess()) {
if(connectfuture!=null) connectfuture.cancel(true);log.debug("Cancelled connection thread scheduler");
} else {
channelFuture.cause().printStackTrace();
connectfuture=channelFuture.channel().eventLoop().scheduleAtFixedRate(new ClientConnectorThread(ClientHandler,IP,port) , 5,30, TimeUnit.SECONDS);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
} );
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Upvotes: 0
Views: 1732
Reputation: 722
When I want to implement re-connection logic, I do it as follows
Add two handlers for pipeline for capturing idle state
pipeline.addLast(new ReadTimeoutHandler(readTimeout, TimeUnit.SECONDS));
pipeline.addLast("ReconnectionHandler", new ReconnectionHandler());
In ReconnectionHandler
capture the user event fired by ReadTimeoutHandler
, disconnect the channel and try to reconnect
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {
ctx.close();
}
} else {
ctx.fireUserEventTriggered(evt);
}
}
public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception {
final EventLoopGroup eventLoopGroup = ctx.channel().eventLoop().parent();
eventLoopGroup.schedule(() -> {
bootstrap.connect()
}, reconnectDelay, TimeUnit.SECONDS);
ctx.fireChannelUnregistered();
}
Upvotes: 0