Supun Kamburugamuva
Supun Kamburugamuva

Reputation: 51

How to use Netty to handle Http Keep-Alive connections

I'm trying to write a HTTP client that uses HTTP keep-alive connections. When I connection from the ClientBoostrap I get the channel. Can I reuse this for sending multiple HTTP requests? Is there any examples demonstrating the HTTP Keep Alive functionality?

Also I have another question. Now my client works without keep-alive connections. I'm calling the channel.close in the messageReceived method of the ClientHandler. But it seems the connections are not getting closed and after some time the sockets run out and I get a BindException. Any pointers will be really appreciated.

Thanks

Upvotes: 4

Views: 9063

Answers (1)

Jonathan Schneider
Jonathan Schneider

Reputation: 27727

As long as the Connection header is not set to CLOSE (and possible the HttpVersion is 1.1, though uncertain) by a line of code similar to this...

request.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);

...your channel should remain open for multiple request/response pairs.

Here is some example code that I whipped up today to test it. You can bounce any number of requests off of Google prior to the channel closing:

 public class TestHttpClient {
    static class HttpResponseReader extends SimpleChannelUpstreamHandler {
        int remainingRequests = 2;

        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
            HttpResponse response = (HttpResponse) e.getMessage();

            System.out.println("Beginning -------------------");
            System.out.println(new String(response.getContent().slice(0, 50).array()));
            System.out.println("End -------------------\n");

            if(remainingRequests-- > 0)
                sendRequest(ctx.getChannel());
            else
                ctx.getChannel().close();
        }
    }

    public static void main(String[] args) {
        ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory());
        bootstrap.setPipeline(Channels.pipeline(
                new HttpClientCodec(),
                new HttpResponseReader()));
        // bootstrap.setOption("child.keepAlive", true); // no apparent effect

        ChannelFuture future = bootstrap.connect(new InetSocketAddress("google.com", 80));
        Channel channel = future.awaitUninterruptibly().getChannel();

        channel.getCloseFuture().addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) throws Exception {
                // this winds up getting called immediately after the receipt of the first message by HttpResponseReader!
                System.out.println("Channel closed");
            }
        });

        sendRequest(channel);

        while(true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static void sendRequest(Channel channel) {
        // Prepare the HTTP request.
        HttpRequest request = new DefaultHttpRequest(
                HttpVersion.HTTP_1_1, HttpMethod.GET, "http://www.google.com");
        request.setHeader(HttpHeaders.Names.HOST, "google.com");
        request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);

        channel.write(request);
    }
}

Upvotes: 2

Related Questions