2016-11-24 214 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會/應該處理。 –