2016-09-01 29 views
1

私はNetty Guideを読みましたが、ChannelFutureについてはあまり説明しません。 ChannelFutureは複雑なアイディアですNetty ChannelFutureの仕組みは?

私がしようとしているのは、初期応答後に文脈にメッセージを書き込むことです。一般的な要求/応答フローとは異なります。リクエスト送信

  1. クライアント - >サーバー(網状)
  2. Serverはctx.writeAndFlush(MSG)との応答を送信する;:私はこのような流れを必要とします
  3. ステップ2が完了したら、サーバはそのctxにさらにメッセージを送信します。

問題は、私はこのような何かを行う場合は、第2の書き込みは送信しないことである。

ctx.writeAndFlush(response); 
Message newMsg = createMessage(); 
ctx.writeAndFlush(newMsg); //will not send to client 

それから私はChannelFutureを使用しようと、それは動作しますが、私は私があればわかりません論理的に正しい:

ChannelFuture msgIsSent = ctx.writeAndFlush(response); 
if(msgIsSent.isDone()) 
{ 
    Message newMsg = createMessage(); 
    ctx.writeAndFlush(newMsg); //this works 
} 

代わりにChannelFutureListener()を使用する必要がありますか?

ChannelFuture msgIsSent = ctx.writeAndFlush(response); 
msgIsSent.addListener(new ChannelFutureListener(){ 
@Override 
public void operationComplete(ChannelFuture future) 
    { 
     Message newMsg = createMessage(); 
     ctx.writeAndFlush(newMsg); 
    } 
}); 

これはこれでもかかりますか?

どちらがベストプラクティスアプローチですか?方法2を使用すると潜在的な問題はありますか?

答えて

2

もちろん、これはあなたの「プロトコル」(HTTPを使用する場合、同じ要求に対して2つの応答を送信することはHTTPプロトコルでサポートされていません)にも依存します。しかし、あなたのプロトコルでは複数の応答部分を送ることができます:

注文を尊重してパイプラインに送るNettyメッセージを追加します。

だからあなたの最初の例では、私は少しそれが動作しません驚いている:

ctx.writeAndFlush(response); 
Message newMsg = createMessage(); 
ctx.writeAndFlush(newMsg); // should send the message 

それはあなたのプロトコルでつながることができたが。例えば、これは起こることができる:あなたのプロトコルは、最初のメッセージがすでに送られていることを認めなければならない場合

response in message queue to send 
flush not yet done 
newMsg in message queue to send 
flush now come but protocol does not support 2 messages so only send first one 

だから、あなたはそうのようなものをやって、最初のを待つ必要があります。

ctx.writeAndFlush(response).addListener(new ChannelFutureListener() { 
    @Override 
    public void operationComplete(ChannelFuture future) { 
    if (future.isDone()) { 
     Message newMsg = createMessage(); 
     ctx.writeAndFlush(newMsg); 
    } else { // an error occurs, do perhaps something else 
    } 
    } 
}); 

だからあなた最後の提案(私はちょうどChannelFutureを作成せずに直接writeAndFlushの結果を使用しましたが、両方とも等価です)。 operationCompleteが成功したということを意味していないケースを世話してください。

-1

#2がうまくいくように見えますが、操作が成功したかどうかを必ず確認してください。そうでない場合は、future.getCause()を使用して例外にアクセスします。機能を変更するわけではありませんが、書き込み呼び出しの結果にリスナーを直接追加するだけでコードを短縮することができます。コールバックで提供されるため、将来を宣言する必要はありません。

0

これを試してみてください:

ctx.channel().writeAndFlush(response); 
    Message newMsg = createMessage(); 
    ctx.channel().writeAndFlush(newMsg); 

Channel.write(..)常にChannelPipelineの尾からのスタート。

ChannelHandlerContext.write(...)は、ChannelHandlerの現在の位置から開始します。