0

IOException何千ものソケット作成呼び出しの後、なぜですか?

接続を受け入れてスレッドを作成し、ソケットを読み取り、別の文字をクライアントに送り返す単純なサーバー コード (Java) を作成しました。各スレッドでクライアントソケットをサーバーマシンに作成し、文字を送信してから、サーバーが送り返す文字をソケットから読み取ります。次に、クライアントとサーバーの両方がソケットを閉じます。

しばらくすると、クライアント側でクライアント ソケットの作成で例外が発生することに気付きました。これを適切に機能させるために考慮すべきいくつかの制限がありますか、またはこれは無限ループで機能する必要がありますか?

ここで、おそらく十分なサイクリング時間の後、クライアント側が新しいソケットをクライアント マシンのポートにバインドしようとする状況を考えています。クライアント マシンは、まだ CLOSED 状態にあるソケットにバインドされていますが、その期間はまだ渡されていないカーネルによって解放されるまでに経過しました。(この期間の正式名称はわかりません) クライアント マシンとサーバー マシンは、VMware の 2 つの Linux システムです。

4

3 に答える 3

0

ありがとうございました !実際、これは私のサーバー側のコードです

public class TestServer {

  public void createThread() {
    System.out.println("createThread");
    ServerThread servThread = new ServerThread();
    servThread.start();   
  }

  public static final void main(String[] args) {

    ServerSocket server = null;

    try {
      System.out.println("Started");
      server = new ServerSocket(12345);
    }
    catch(IOException ex) {
      System.out.println("Server: Exception at socket creation: " + ex.getMessage());
    }

    try {
      while(true) {
        Socket clientSock = server.accept();
        System.out.println("Connection Accepted: server: "+clientSock.getLocalPort()+", Client: "+clientSock.getPort());
        ServerThread servThread = new ServerThread(clientSock);
        servThread.start();
      }
    }
    catch(IOException ex) {
      System.out.println("Server: Exception at socket accept: " + ex.getMessage());
    }

  }
}

class ServerThread extends Thread {

  private Socket sock;

  public ServerThread() {}

  public ServerThread(Socket sock) {
    this.sock = sock;
  }

  public void run() {
    InputStream is = null;
    OutputStream os = null;
    try {
      is = sock.getInputStream();
      os = sock.getOutputStream();
    }
    catch(IOException ex) {}  

    try {     
      int b = is.read();
      System.out.println("server: received = " + (char)b);
    }
    catch(IOException ex) {
      System.out.println("Server: IOException at read = " + ex.getMessage());
    }

    try {
      os.write('R');
      os.flush();
    }
    catch(IOException ex) {
      System.out.println("Server: IOException at write = " + ex.getMessage());
    }

    try {
      sock.close();
    }
    catch(IOException ex) {
      System.out.println("Server: IOException at close = " + ex.getMessage());
    }
  }
}

これはクライアント部分です:

public class TestClient {

  public static void main(String[] args) {

    if (args.length != 4) {
      System.out.println("Usage: java TestClient <ServerIP> <nbThreads> <cycle> <delay>");
      System.exit(1);
    }

    String host   = args[0];
    int nbThreads = Integer.parseInt(args[1]);
    int cycle     = Integer.parseInt(args[2]);
    int delay     = Integer.parseInt(args[3]);

    for (int i = 0; i<cycle; i++) {
      for (int j = 0; j<nbThreads; j++) {
        ClientThread clThread = new ClientThread(host);
        clThread.start();
      }
/*      try {
        Thread.sleep(delay);
      }
      catch (Exception ex) {} */
    }
  }
}

class ClientThread extends Thread {

  private String host;

  public ClientThread(String host) {
    this.host = host;
  }

  public void run(){

    for (int i=0; i<3; i++) {
      Socket clientSock = null;
      try {
        clientSock = new Socket(host, 12345);
      }
      catch(IOException ex) {
        System.out.println("Client: IOException at socket creation = " + ex.getMessage());
      }

      OutputStream os = null;
      InputStream  is = null;
      try {
        os = clientSock.getOutputStream();
        is = clientSock.getInputStream();
      }
      catch (IOException ex) { }

      try {
        os.write('B');
        os.flush();
      }
      catch (IOException ex) {
        System.out.println("Client: IOException at write = " + ex.getMessage());
      }

      try {
        int reply = is.read();
        System.out.println("Client: reply = " + (char)reply);
      }
      catch(IOException ex) {
        System.out.println("Client: IOException at read = " + ex.getMessage());
      }

      try {
        clientSock.close();
      }
      catch(IOException ex) {
        System.out.println("Client: IOException at close = " + ex.getMessage());
      }
    }
  }
}

60 スレッド、1000 サイクル、遅延なしでテストしています。

私は最初の質問で間違っていました。例外は、しばらくすると is.read() 呼び出しから発生し、「接続リセット」例外です。このサンプル コードを実行して、クライアント ソケットの作成中に例外が発生するアプリケーション コードで発生している問題をシミュレートしましたが、これとアプリケーション コードの違いをさらに見つける必要があるようです。 . ただし、しばらくするとクライアント側で「接続リセット」例外が発生する理由を理解するのにも役立つと思います。サーバー側で os.write('R') が発生すると、 sock.close() が非常に速く発生するため、クライアント側では is.read() 呼び出しがまだ到達していない可能性があります。奇妙に聞こえます:)

また、どのソケットで setReuseAddress 関数を使用する必要があるかもわかりません。ソケットを何度も作成しているため、クライアント側ではありません...ただし、クライアントソケットの作成時に例外が発生していません。ありがとう !

于 2013-05-16T09:31:20.960 に答える
0

接続が切断された可能性があります。

「分散コンピューティングの誤謬」のルール #1 を忘れていました: ネットワークは常に信頼できます。

于 2013-05-15T15:44:34.747 に答える