2016-11-24 13 views
0

私は比較的新しいものですが、正しく動作しているかどうかは不明です。私は可能な限り短くしようとします。何か不明な点がある場合は、詳細情報をお尋ねください。NettyでHTTPクライアント例外を処理します。

したがって、私はHTTPリクエストを処理するNettyサーバーを持っています。コンテンツは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)); 
} 

まず2つのチャネルハンドラは標準ネッティーものです、

を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はそれを処理するはずです。 –