2016-11-24 213 views
0

我对netty比较陌生,如果我正确地做事,我不确定。我会尽量缩短。如果有任何疑问,请询问更多信息。在netty中处理HTTP客户端异常

所以,我有一个netty服务器提供HTTP请求,其中内容预计是序列化为Json字符串的protobuf消息。

通道管道是这样的:

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

因此,我在HttpToProtobufDecoder中收到FullHttpRequest并尝试将请求的内容解码为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响应后?

我是否会以正确的方式去做这件事?我应该在exceptionCaught中写入HTTP响应消息吗?

对不起,如果问题有点不清楚。任何帮助都感激不尽!

/谢谢!

回答

2

客户端无法知道您的邮件何时完全发送。添加内容长度或分块标题,您不需要关闭连接。

+0

谢谢!我自己得出了这个确切的结论。很高兴得到证实。我不知何故,虽然HttpServerCodec会/应该处理。 –