Как использовать Netty для обработки соединений Http Keep-Alive - PullRequest
3 голосов
/ 23 февраля 2012

Я пытаюсь написать HTTP-клиент, который использует HTTP-соединения keep-alive. Когда я соединяюсь с ClientBoostrap, я получаю канал. Могу ли я использовать это для отправки нескольких HTTP-запросов? Есть ли примеры, демонстрирующие функциональность HTTP Keep Alive?

Также у меня есть еще один вопрос. Теперь мой клиент работает без keep-alive соединений. Я звоню channel.close в методе messageReceived ClientHandler. Но кажется, что соединения не закрываются, и через некоторое время сокеты заканчиваются, и я получаю BindException. Любые указатели будут по достоинству оценены.

Спасибо

1 Ответ

2 голосов
/ 30 июня 2012

До тех пор, пока заголовок Соединения не установлен на ЗАКРЫТО (и, возможно, HttpVersion равен 1.1, хотя и неопределенен) строкой кода, подобной этой ...

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

... ваш канал должен оставаться открытым для нескольких пар запрос / ответ.

Вот пример кода, который я сегодня взбил для его проверки.Вы можете отклонить любое количество запросов от Google до закрытия канала:

 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);
    }
}
...