私は、以下の条件を満たしてネッティーサーバーを作っています:それはそのクライアントからのパケットを受信したときクライアントが切断されたとき、Nettyサーバはどのように知っていますか?
- サーバは、トランザクション処理Aを行う必要があります。
- トランザクションが終了すると、まだ接続されていれば、クライアントに戻りメッセージを返します。そうでない場合は、いくつかのロールバックプロセスBを実行してください。
しかし、私の問題は、クライアントに返信すると、サーバはまだ接続されているかどうかを知りません。
メッセージを送信する前に、次のコードを試して接続を確認しました。しかし、クライアントがすでにソケットを閉じても常に成功します。クライアントプロセスが強制的に(例えば、Ctrl + Cを)殺害された場合にのみ、私はこれが原因でTCPプロトコルであると思っ
final ChannelFuture cf = inboundChannel.writeAndFlush(resCodec);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
inboundChannel.close();
} else {
try {
// do Rollback Process B Here
}
}
});
失敗しました。クライアントが正常に切断されると、FIN信号がサーバーに送信されます。それで、writeAndFlushは、それがしなくても何とか成功すると思います。
だから、例外が私の場合に発生する(常にtrueを返す)
if(inboundChannel.isActive()){
inboundChannel.writeAndFlush(msg);
} else{
// do RollBack B
}
// Similar codes using inboundChannel.isOpen(), inboundChannel.isWritable()
どちらも「ピアによって接続リセット」「channelInactive」イベントもが、私はあまりにも、次のコードを試してみたが、これらは同じ結果を持っています。
これは私が使用したNettyテストクライアントコードの一部です。
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE);
}
どのように私は私が返信したい時に切断に気付くことができますか?
これは、SMTPプロトコルで発生する可能性のある同じ問題です。メールサーバーはメールを受信しましたが、クライアントはそれを認識しません。これが解決できる方法の1つは、クライアント側で生成されたトランザクション番号を使用することです。クライアントが「再接続」すると、そのトランザクションIDに関する状態を尋ねます – Ferrybig
切断されたクライアントを検出した場合でもロールバックを試みるべきではありません。彼はあなたにトランザクションを実行するように言った、あなたはそれを実行した:あなたは彼にそれを確認することはできませんが、それは問題ではなく、あなたのものです。その解決策は、トランザクションが*冪等であるように設計することです。つまり、既に適用されているトランザクションを再適用することは何もしません。 – EJP