2
votes

Retry Connection in Netty

I am building a client socket system. The requirements are: First attemtp to connect to the remote server When the first attempt fails keep on trying until the server is online.

I would like to know whether there is such feature in netty to do it or how best can I solve that.

Thank you very much

This is the code snippet I am struggling with:

protected void connect() throws Exception {

        this.bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(),
                Executors.newCachedThreadPool()));

        // Configure the event pipeline factory.
        bootstrap.setPipelineFactory(new SmpPipelineFactory());

        bootstrap.setOption("writeBufferHighWaterMark", 10 * 64 * 1024);
        bootstrap.setOption("sendBufferSize", 1048576); 
        bootstrap.setOption("receiveBufferSize", 1048576);
        bootstrap.setOption("tcpNoDelay", true);
        bootstrap.setOption("keepAlive", true);
        // Make a new connection.
        final ChannelFuture connectFuture = bootstrap
                .connect(new InetSocketAddress(config.getRemoteAddr(), config
                        .getRemotePort()));

        channel = connectFuture.getChannel();
        connectFuture.addListener(new ChannelFutureListener() {

            @Override
            public void operationComplete(ChannelFuture future)
                    throws Exception {
                if (connectFuture.isSuccess()) {
                    // Connection attempt succeeded:
                    // Begin to accept incoming traffic.
                    channel.setReadable(true);
                } else {
                    // Close the connection if the connection attempt has
                    // failed.
                    channel.close();
                    logger.info("Unable to Connect to the Remote Socket server");                   
                }

            }
        });
    }
2
There is no built in feature to do that, you would need to do it yourself.Brian Roach
@BrianRoach: Can you please guide me in implementing such a requirement because I am not a geek in netty.Arsene
Unfortunately that is well beyond the scope of an answer on StackOverflow. Writing a client with netty is not easy and requires a fair amount of understanding of the framework. To point you in the right direction you need to look at Channel.closeFuture() - you need to register a ChannelFutureListener and get notified when that future completes (meaning the channel is closed).Brian Roach
And actually, on the initial connection attempt you use the Future returned by the bootstrap's connect() call - that I can reasonably answer here - sec.Brian Roach
@BrianRoach: Thank you. I did the connect and future. That helps me check whether the connection successful or not. The issue is when It failed how to retry it until I get connected when server available.Arsene

2 Answers

2
votes

Assuming netty 3.x the simplest example would be:

// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
        new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(),
                Executors.newCachedThreadPool()));


ChannelFuture future = null;

while (true)
{
    future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 80));
    future.awaitUninterruptibly();
    if (future.isSuccess()) 
    {
        break;
    }
}

Obviously you'd want to have your own logic for the loop that set a max number of tries, etc. Netty 4.x has a slightly different bootstrap but the logic is the same. This is also synchronous, blocking, and ignores InterruptedException; in a real application you might register a ChannelFutureListener with the Future and be notified when the Future completes.

Add after OP edited question:

You have a ChannelFutureListener that is getting notified. If you want to then retry the connection you're going to have to either have that listener hold a reference to the bootstrap, or communicate back to your main thread that the connection attempt failed and have it retry the operation. If you have the listener do it (which is the simplest way) be aware that you need to limit the number of retries to prevent an infinite recursion - it's being executed in the context of the Netty worker thread. If you exhaust your retries, again, you'll need to communicate that back to your main thread; you could do that via a volatile variable, or the observer pattern could be used.

When dealing with async you really have to think concurrently. There's a number of ways to skin that particular cat.

1
votes

Thank you Brian Roach. The connected variable is a volatile and can be accessed outside the code or further processing.

final InetSocketAddress sockAddr = new InetSocketAddress(
                config.getRemoteAddr(), config.getRemotePort());
    final ChannelFuture connectFuture = bootstrap
            .connect(sockAddr);

    channel = connectFuture.getChannel();
    connectFuture.addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future)
                throws Exception {
            if (future.isSuccess()) {
                // Connection attempt succeeded:
                // Begin to accept incoming traffic.
                channel.setReadable(true);
                connected = true;
            } else {
                // Close the connection if the connection attempt has
                // failed.
                channel.close();                    
                if(!connected){
                    logger.debug("Attempt to connect within " + ((double)frequency/(double)1000) + " seconds");
                    try {
                        Thread.sleep(frequency);
                    } catch (InterruptedException e) {
                        logger.error(e.getMessage());
                    }   
                    bootstrap.connect(sockAddr).addListener(this);                                          
                }
            }

        }
    });