2010-12-30 7 views
2

私は、クライアントがクラッシュしたかどうかを検出するためにキープアライブメカニズムを実装する必要があるクライアント/サーバアプリケーションを構築しています。私は、クライアント側とサーバー側の両方に別々のスレッドを持っています。クライアントスレッドは "ping"を送信して3秒間スリープし、サーバはBufferedInputStreamを読み込み、pingが受信されたかどうかをチェックし、そうであればpingカウンタをゼロにし、そうでない場合は+1し、サーバスレッド3秒間スリープし、pingカウンタが3に達すると、クライアントは死んだと宣言します。Javaでキープアライブを実装する

問題は、サーバーが入力ストリームを読み込み、ブロッキングコールを読み込んだときに、次のpingが受信されるまでブロックされ、遅れているかどうかに関係なくブロックされるため、サーバーはpingが見つからないことを検出しません。

ストリームの現在の値を読み取ることができるように、入力ストリームに何もない場合はブロックされません。

おかげで、

+0

"サーバーがPingを検出しない"と説明してください。 –

+0

たとえば、クライアントは3秒ごとにキープアライブを送信しており、サーバーはキープアライブも3秒ごとに確認しています。クライアントがkeep-aliveを10秒間送信しないと、サーバーがキープアライブをチェックすると、何も読み取られず、クライアントから何も送られないので、ストリームから読み取る呼び出しはそれまでブロックされません10秒後に次のキープアライブを受信します。その時点で、サーバはキープアライブを受信したことを喜んで宣言します。だから失われたキープ・アライブを決して検出しません。 – comatose

答えて

5

のJava 1.4はjava.nioパッケージに代表される非ブロックI/Oの考え方を導入しました。これはおそらくあなたが必要とするものです。

this tutorial for how to use non-blocking I/Oを参照してください。

また、これは宿題や学習の練習ではないと仮定し、Apache MinaJBoss Nettyなどのより堅牢なプロトコルフレームワークを使用することをお勧めします。それらの間のthis comparisonを参照して、なぜそれらを使用したいでしょうか。

0

すべてのブロッキング接続を監視する別個の監視スレッドを持つことができます。接続が何かを受け取ると、カウンタをリセットすることができます。 (私はどんなパケットでもハートビートとして扱います)監視スレッドは実行するたびにこのカウンタをインクリメントすることができ、制限に達すると(つまりゼロにリセットされなかったため)、接続を閉じることができます。そのようなスレッドは1つだけ必要です。最後に閉じた接続でブロックしているスレッドはIOExceptionをスローし、スレッドをスリープ状態にします。

一方、ハートビートは、パケットが一定期間送信されなかった場合にトリガーされます。これは、ビジーな接続がハートビートを送信しないことを意味します。