ソケットのInputStreamの内容は、閉じるときに書き込み後にアクセスできません

冬:

閉じたばかりのソケット入力ストリームのコンテンツ全体を読み取ろうとしています。しかし、それを読み取ってみても通常は機能しますが、常にそのソケットの出力ストリームに同時に書き込みを試みています。それに書き込むと、ソケットの入力ストリームが「壊れ」、残りを読み取ることができなくなります。

私の問題を説明するために作成したこの小さな例を見てみましょう。

@Test
public void socketTest() throws Throwable
{
    new Thread(() -> {
        try
        {
            ServerSocket serverSocket = new ServerSocket(5555);

            while(true)
            {

                //keep listening
                Socket socket = serverSocket.accept();

                InputStream in = socket.getInputStream();

                System.out.println(in.read());

                Thread.sleep(2000);

                try
                {
                    socket.getOutputStream().write(3);
                }
                catch(Throwable ex)
                {
                    System.out.println("Error writing");
                    ex.printStackTrace();
                }

                System.out.println(in.read());

                in.close();
                socket.close();
                System.exit(0);
            }
        }
        catch(Throwable ex)
        {
            System.out.println("Error reading");
            ex.printStackTrace();
        }
    }).start();

    Thread.sleep(100); //you might need this
    Socket socket = new Socket("localhost", 5555);
    OutputStream out = socket.getOutputStream();
    out.write(1);
    out.write(2);
    out.close();
    socket.close();

    synchronized(this)
    {
        wait();
    }
}

私は出力を取得します:

1
java.net.SocketException: Software caused connection abort: recv failed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.net.SocketInputStream.read(SocketInputStream.java:223)
    at net.jumpai.test.SocketTTest.lambda$socketTest$0(SocketTTest.java:55)
    at java.lang.Thread.run(Thread.java:745)
Error reading

ただし、2が読み取られることはなく、ストリームに3を書き込むことでエラーが発生することはありません。ストリームで書き込みをスローしてもかまいませんが、2を読みたいのですが、それを行う方法はありますか?

私はjdk1.8.0_91がインストールされたWindows 7を使用しています。jdk1.8.0_181(現在の最新バージョン)に更新した後でも、問題を再現できました。Java 1.8.0_111を搭載した別のWindows 7コンピューターで再現することもできます。

ArchLinux open-jdk1.8.0_172でバグを再現できませんでした。これは、Javaバージョンのバグであることを意味しますか?それは本当にWindowsまたは少なくともOracleの実装にリンクされているようです。

冬:

この動作は、どのバージョンの2つのWindowsマシンでも簡単に再現できますが、LinuxまたはMacシステムでは再現できません。open-jdkには存在しないOracleのJVMのバグだと思います。

このバグはかなり煩わしいものであり、誰かが回避策を投稿していただければ幸いです。一方、Oracleにバグレポートを提出しました:https : //bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8208479

回避策を構築しようとすると、システムにバグがあるかどうかを確認できるようになりました。

public static boolean hasOracleSocketBug()
{
    try
    {
        int port = 10000;

        while(!PortChecker.portAvailable(port))
            port++;

        ServerSocket serverSocket = new ServerSocket(port);

        int fPort = port;
        new Thread(() -> {
            try
            {
                Socket socket = new Socket("localhost", fPort);
                OutputStream out = socket.getOutputStream();
                out.write(1);
                out.write(2);
                out.close();
                socket.close();
            }
            catch(Exception ex)
            {
                try
                {
                    serverSocket.close();
                }
                catch(IOException ignored) {}
            }
        }).start();

        Socket socket = serverSocket.accept();

        InputStream in = socket.getInputStream();
        in.read();
        socket.getOutputStream().write(3);

        try
        {
            in.read();
        }
        catch(Exception ex)
        {
            socket.close();
            return true;
        }

        in.close();
        socket.close();
        return false;
    }
    catch(Throwable ignored)
    {
        return false;
    }
}

public static boolean portAvailable(int port)
{
    ServerSocket ss = null;
    try
    {
        ss = new ServerSocket(port);
        ss.setReuseAddress(true);
        return true;
    }
    catch(IOException ignored)
    {
        return false;
    }
    finally
    {
        if(ss != null)
        {
            try
            {
                ss.close();
            }
            catch(IOException ignored) {}
        }
    }
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

ソケットは書き込みストリームでは閉じられますが、読み取り時には閉じられません

分類Dev

golang tcpソケットはget File()の後に閉じることができません

分類Dev

サーバーに読み取り/書き込みを許可することはできますが、Google Cloud Storageバケットへのアクセス許可を削除することはできませんか?

分類Dev

PHP-fwrite()はソケットに書き込みません

分類Dev

ソケットに書き込んだ後、プログラムは自動的に閉じます

分類Dev

ソース 'Microsoft.Practices.EnterpriseLibrary.Data'のログを開くことができません。イベントログの読み取り/書き込み時に書き込みアクセス権がない可能性があります

分類Dev

Ubuntu 17.10にアップグレードした後、NTFSパーティションの書き込み権限にアクセスできません

分類Dev

ソケットが閉じるか、改行が書き込まれるまで、TCPConn Writeは何もしません

分類Dev

fs.writeFile()は、スクリプトを閉じるときに、実際のオブジェクトの代わりに[object、object]を書き込みます

分類Dev

書き込みコンテキストでメソッドの戻り値を使用することはできません。セッションデータ

分類Dev

閉じたiframeの後にリンクをクリックすることはできません

分類Dev

KeyboardInterruptのソケットを閉じることができません

分類Dev

閉じた接続に書き込もうとしても、ソケットは例外をスローしません

分類Dev

ページの読み込み時にJavaスクリプトの拡大ポップアップボックスを閉じることができません

分類Dev

ログアウト時にソケットを閉じることができません

分類Dev

JavaScriptはobject.create(baseObject)の後に同じオブジェクトメソッドにアクセスできません

分類Dev

EPPlusは閉じたストリームにアクセスできません

分類Dev

NginxはCentOS7のuWSGIunixソケットにアクセスできません

分類Dev

閉じたソケットに書き込み、壊れたパイプのエラーを強制的に修正できますか?

分類Dev

別のスレッドからaccept()/ select()を中止するためにリスニングソケットを閉じることができません

分類Dev

メモリストリームにアップロードするときに閉じたファイルにアクセスできません

分類Dev

ソースの内容に応じて日付を書き込めません

分類Dev

ソケットへの書き込み時の例外:トランスポート接続にデータを書き込めません

分類Dev

ファイルの内容が閉じられた後にのみ書き込まれるのはなぜですか?

分類Dev

BufferedWriter は、フラッシュして閉じた後にファイルに書き込みません

分類Dev

ソケットからの読み取り時に書き込み操作でスタックする

分類Dev

Rでは、同じコードをパッケージのVignetteファイルに組み込むことはできません。「リスト」オブジェクトは整数型に強制変換できません

分類Dev

CまたはC ++の同じソケットで同時に読み書き

分類Dev

Systemdソケットのアクティブ化:ソケットを閉じるときにbashスクリプトを強制終了します

Related 関連記事

  1. 1

    ソケットは書き込みストリームでは閉じられますが、読み取り時には閉じられません

  2. 2

    golang tcpソケットはget File()の後に閉じることができません

  3. 3

    サーバーに読み取り/書き込みを許可することはできますが、Google Cloud Storageバケットへのアクセス許可を削除することはできませんか?

  4. 4

    PHP-fwrite()はソケットに書き込みません

  5. 5

    ソケットに書き込んだ後、プログラムは自動的に閉じます

  6. 6

    ソース 'Microsoft.Practices.EnterpriseLibrary.Data'のログを開くことができません。イベントログの読み取り/書き込み時に書き込みアクセス権がない可能性があります

  7. 7

    Ubuntu 17.10にアップグレードした後、NTFSパーティションの書き込み権限にアクセスできません

  8. 8

    ソケットが閉じるか、改行が書き込まれるまで、TCPConn Writeは何もしません

  9. 9

    fs.writeFile()は、スクリプトを閉じるときに、実際のオブジェクトの代わりに[object、object]を書き込みます

  10. 10

    書き込みコンテキストでメソッドの戻り値を使用することはできません。セッションデータ

  11. 11

    閉じたiframeの後にリンクをクリックすることはできません

  12. 12

    KeyboardInterruptのソケットを閉じることができません

  13. 13

    閉じた接続に書き込もうとしても、ソケットは例外をスローしません

  14. 14

    ページの読み込み時にJavaスクリプトの拡大ポップアップボックスを閉じることができません

  15. 15

    ログアウト時にソケットを閉じることができません

  16. 16

    JavaScriptはobject.create(baseObject)の後に同じオブジェクトメソッドにアクセスできません

  17. 17

    EPPlusは閉じたストリームにアクセスできません

  18. 18

    NginxはCentOS7のuWSGIunixソケットにアクセスできません

  19. 19

    閉じたソケットに書き込み、壊れたパイプのエラーを強制的に修正できますか?

  20. 20

    別のスレッドからaccept()/ select()を中止するためにリスニングソケットを閉じることができません

  21. 21

    メモリストリームにアップロードするときに閉じたファイルにアクセスできません

  22. 22

    ソースの内容に応じて日付を書き込めません

  23. 23

    ソケットへの書き込み時の例外:トランスポート接続にデータを書き込めません

  24. 24

    ファイルの内容が閉じられた後にのみ書き込まれるのはなぜですか?

  25. 25

    BufferedWriter は、フラッシュして閉じた後にファイルに書き込みません

  26. 26

    ソケットからの読み取り時に書き込み操作でスタックする

  27. 27

    Rでは、同じコードをパッケージのVignetteファイルに組み込むことはできません。「リスト」オブジェクトは整数型に強制変換できません

  28. 28

    CまたはC ++の同じソケットで同時に読み書き

  29. 29

    Systemdソケットのアクティブ化:ソケットを閉じるときにbashスクリプトを強制終了します

ホットタグ

アーカイブ