2016-11-24 3 views
0

Я относительно новый с netty и не уверен, что я делаю все правильно. Я постараюсь быть как можно короче. Пожалуйста, задайте больше информации, если что-то неясно.Обработать исключение HTTP-клиента в netty

Итак, у меня есть сетчатый сервер, обслуживающий HTTP-запросы, где ожидается, что содержимое сообщения protobuf будет сериализовано для строк Json.

Трубопровод канала выглядит следующим образом:

@Override protected void initChannel(final SocketChannel channel) throws Exception { 
    final ChannelPipeline pipeline = channel.pipeline(); 
    pipeline.addLast(new HttpServerCodec()); 
    pipeline.addLast(new HttpObjectAggregator(1048576)); 
    pipeline.addLast(new HttpProtobufServerCodec(charset, requestConverter, responseConverter)); 
    pipeline.addLast(new ProtobufMessageHandler(mapping)); 
} 

Первого два обработчик канала является стандартной Нетти материал,

HttpProtobufServerCodec выглядит следующим образом:

public class HttpProtobufServerCodec extends CombinedChannelDuplexHandler<HttpToProtobufDecoder, ProtobufToHttpEncoder> 

и HttpToProtobufDecoder выглядит следующим образом:

public final class HttpToProtobufDecoder extends MessageToMessageDecoder<FullHttpRequest> { 
    private Charset charset; 
    private final Converter<byte[], ?> converter; 

    protected HttpToProtobufDecoder(final Charset charset, final Converter<byte[], ?> converter) { 
     this.charset = charset; 
     this.converter = converter; 
    } 

    @Override protected void decode(final ChannelHandlerContext ctx, final FullHttpRequest msg, final List<Object> out) 
      throws Exception { 
     byte[] payloadBytes = new byte[msg.content().readableBytes()]; 
     msg.content().readBytes(payloadBytes); 
     Message message = (Message) converter.convert(payloadBytes); 
     out.add(message); 
    } 

    @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { 
     FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, 
        HttpResponseStatus.BAD_REQUEST, 
        Unpooled.wrappedBuffer(charset.encode("Could not read request!").array())); 

     //ctx.writeAndFlush(response); 
     ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); 
    } 
} 

Итак, я получаю FullHttpRequest в HttpToProtobufDecoder и пытаюсь декодировать содержимое запроса в сообщении protobuf. Это порождает исключение, если контент не может быть декодирован, что помещает нас в метод exceptionCaught (...).

В Исключении пойманный ответ HTTP 400 создается и записывается в channelHandlerContext. Здесь у меня есть мой вопрос.

если комментарии по следующим направлениям включаются:

//ctx.writeAndFlush(response); 
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); 

клиент таймаут при чтении тела ответа. Но если я закрою канал после записи 400, все будет хорошо. Что происходит? чтение входного потока блокируется, потому что нет доступных входных данных. То есть мы застряли в in.read (...) ниже, где-то далеко вниз в коде клиента:

while ((bytesRead = in.read(buffer)) != -1) { 
     out.write(buffer, 0, bytesRead); 
     byteCount += bytesRead; 
    } 

Итак, вопрос в том, есть ли у вас близкий канал после написания ответа HTTP 400 для какой-то причины ?

Я даже об этом правильно? Должен ли я писать ответное сообщение HTTP в exceptionCaught?

Извините, если вопрос немного неясен. Любая помощь будет высоко ценится!

/Спасибо!

ответ

2

Клиент не имеет возможности узнать, когда ваше сообщение было полностью отправлено. Добавьте длину содержимого или фрагментированный заголовок, и вам больше не нужно будет закрывать соединение.

+0

Спасибо! Я сам пришел к этому точному выводу. Приятно подтвердить это. Я каким-то образом, хотя HttpServerCodec должен/должен справиться с этим. –