0

ここで説明されているのと同様の問題が発生しています: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%確信が持てません。ソケットルーチンに多くのデバッグ出力を追加しましたが、次回の準備が整いました。

すべての有益なコメントをありがとう!

4

2 に答える 2

2

正しく完了していない接続から読み取っています。OP_CONNECTおそらく、非ブロッキングモードで接続を行い、イベントを受信して​​いない可能性があります。あなたは電話をしていませんfinishConnect(); またはそれは戻りませんでしたtrue

于 2012-07-18T10:34:59.020 に答える
0

クライアントが接続を試みましたが、応答がなく、最終的にタイムアウトになりました。

EJP、訂正ありがとうございます。

于 2012-07-18T09:39:34.287 に答える