TCP受信バッファに入力データが残っているNettyで接続を閉じるときに、TCP FINフラグではなくTCP RSTフラグが設定されないようにする方法があるかどうか疑問に思っています。
使用例は次のとおりです。
- クライアント (C で記述) は、多くのフィールドを含むデータ パケットを送信します。
- サーバーはパケットを読み取り、初期フィールドでエラーに遭遇し、例外をスローします。
- 例外ハンドラーは例外をキャッチし、エラー メッセージを書き込み、write フューチャーに close on write コールバックを追加します。
問題は:
受信バッファにデータが残っていると、Linux (または Java..) は RST フラグで TCP パケットにフラグを立てます。これにより、クライアントがデータを読み取ろうとすると、ソケットが閉じられているために読み取りエラーが発生することが判明するため、クライアントはデータを読み取ることができなくなります。
ストレート Java ソケットの場合、解決策は、閉じる前に socket.shutdownOutput() を呼び出すことだと思います。Netty またはこれを回避する方法に同等の機能はありますか?
単にソケットからの読み取りを続行すると、RST を回避するには不十分な場合があります。これは、close が呼び出されたときにバッファーにデータがある場合とない場合があるためです。
参考:http ://cs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf
アップデート:
問題の別の参照と説明: http://docs.oracle.com/javase/1.5.0/docs/guide/net/articles/connection_release.html
shutdownOutput() を呼び出すと、(FIN を送信することにより) 接続をより整然と閉じるのに役立ちますが、クライアントがまだデータを送信している場合は、関係なく RST メッセージが送信されます (EJP からの回答を参照してください。shutdownOutput() に相当するものを利用できる場合があります)。 Netty 4+で。
解決策は、クライアントからすべてのデータを読み取ることです (ただし、特に悪意のあるクライアントの場合、クライアントが送信を完全に停止する時期を確認することはできません)、または応答を送信した後、接続を閉じる前に単に待機することです (回答を参照)評判の悪いから)。