ここで説明されているのと同様の問題が発生しています:JavaLinuxノンブロッキングソケットタイムアウト動作
JavaNIOで実装されたアプリケーションがあります。一連のソケットを追跡し、それらを読み取る準備ができると、アプリケーションはループで読み取ります(コードを削除し、簡潔にするためにいくつかのロジックを使用します)。
if (selkey.isReadable()) {
int nread;
while (true) {
// read the header
nread = mSocketChannel.read(mHeaderBuffer);
if (nread == -1)
return;
handle_message_header();
// read the body
nread = mSocketChannel.read(mPayloadBuffer);
if (nread == -1)
return;
handle_message_body();
}
}
しかし、ごくまれに、最初のread()でタイムアウト例外が発生します。
java.io.IOException: Connection timed out
at sun.nio.ch.FileDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:21)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:202)
at sun.nio.ch.IOUtil.read(IOUtil.java:175)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:243)
jdkソースを掘り下げたところ、read0関数はソケットハンドルでread()を呼び出すだけです。read()が-1を返し、errno == ETIMEDOUTの場合、「接続がタイムアウトしました」例外がスローされます。
soSetTimeout()またはtcpキープアライブオプションは使用しません。そして、これはクライアントのクラスターでのみ表示されていたため、再現できません(netstatやその他のツールの出力もありません)。
Linuxカーネルがノンブロッキングread()でETIMEDOUTを返すのはどのような場合ですか?これはバグですか、それとも機能ですか?
これが表示されたマシンに関する詳細情報:
Linux slave1 2.6.18-164.e15 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
CentOS 5.4
ありがとうクリス
編集:私のログファイル(およびプログラムフロー)によると、サーバーが着信接続を受け入れたときにソケットが作成されました。次に、そのソケットから少なくとも1つの正常な受信がありましたが、サーバーの2倍が書き込みに失敗しました。そして、私は読んでいるときに例外を見つけました。ログファイルには多くの情報が含まれていません。したがって、これまでのところ、分析について100%確信が持てません。ソケットルーチンに多くのデバッグ出力を追加しましたが、次回の準備が整いました。
すべての有益なコメントをありがとう!