5

この質問に対する満足のいく答えをどこにも見つけることができませんでした。内部事情に詳しい方、教えていただけないでしょうか。

この問題を説明するために、単純なクライアント/サーバーを作成しました。 サーバーは 1 行のテキストを読み取り、ソケットを閉じます。クライアントは 1 行のテキストを書き込み、10 秒待ってから、さらに 2 行のテキストを書き込みます。2 回目の書き込み (10 秒後) は失敗しますが、最初の書き込みは常に成功します。

BufferedWriter が最初の書き込み自体で例外をスローできないのはなぜですか? 結局、ソケットはずっと前に閉じられていました。コードはまた、最初の書き込みの直前にソケットで読み取りを行い、-1 を返して、入力側がソケットのクローズを既に検出したことを示します。なぜ出力側もこれを知ることができないのですか?

  public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(9000);
        Socket s = ss.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        System.out.println(in.readLine());
        s.close();
        System.out.println("Socket closed");
    }
  }

  public class Client {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket s = new Socket("localhost", 9000);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        out.write("Hello, World!\n"); out.flush();
        Thread.sleep(10000);
        System.out.println("Read from socket returns: " + s.getInputStream().read());
        out.write("First write\n"); out.flush();
        System.out.println("First write succeeded without detecting socket closed");
        out.write("Second write\n"); out.flush();
        System.out.println("Second write succeeded without detecting socket closed");
    }
  }
4

2 に答える 2

4

リモート クローズは、出力のリモート シャットダウンと区別がつきません。どちらの場合も、このエンドは FIN を受信します。これは、ピアが送信を停止したことを意味します。実際に入力のためにシャットダウンしたとしても、彼が受信を停止したという兆候はありません。したがって、送信者が検出できる唯一の方法は、送信時に RST を取得することであり、送信されたデータがソケット送信バッファーよりも大きい場合を除き、定義上、最初の送信では発生しません。

于 2013-12-11T07:06:53.253 に答える
0

私たちはプロジェクトでこれを見ました。私は、インターネット プロトコルが多かれ少なかれ TCP/IP ソケットがこれを行うことを保証していると考えています。

IP プロトコルは、可能な限り最善の方法でパケットをルーティングすることを目的としています。書き込み/配信が失敗した後にのみ、相手側で接続が失われたことがわかります。インターネットは回復力があるように設計されており、メッセージを配信するためにさまざまなルートなどを試すように設計されていることを思い出してください。

ネットワークとデータリンクのトランスポートが異なると、動作が異なる場合があります。かなり前に、tcp/ip 経由でセッション レイヤーを実行する必要がありましたが、この問題は奇妙に聞き覚えがあります。

メイン送信の前にいくつかのテスト バイトを送信することで回避できるようです。

于 2015-05-13T06:57:51.033 に答える