Вот коды, я думаю, что они все в порядке, однако JRE так не считает

Вот коды сервера

    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.BufferedReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.ServerSocket;
    import java.io.IOException;

    public class MyServer {
      private int port;
      private ServerSocket sSocket = null;

      public MyServer(int port) throws IOException {
        this.port = port;
        sSocket = new ServerSocket(port);
      }
      public MyServer() throws IOException {
        this(10005);
      }

      public void serve() {
        Socket socket = null;
        while (true) {
          try {
        socket = sSocket.accept();
        new MyThread(socket).start();
          } catch (IOException e) {
        e.printStackTrace();
          } finally {
        try {
          if (sSocket != null) sSocket.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
          }
        }
      }

      public static void main(String[] args) throws IOException {
        new MyServer().serve();
      }
    }

    class MyThread extends Thread {
      Socket socket;

      public MyThread(Socket s) {
        socket = s;
      }

      public void run() {
        try {
          BufferedReader reader = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));
          PrintWriter writer = new PrintWriter(socket.getOutputStream());

          String msg = null;
          while((msg = reader.readLine()) != null) {
        System.out.print("Get:\t" + msg + "\nSending back...");
        writer.println("Echo" + msg);
        System.out.println("done.");

        if (msg.equals("bye")) break;
          }
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          try {
        if (socket != null) socket.close();
          } catch (IOException e) {
        e.printStackTrace();
          }
        }
      }
    }

Вот коды клиента.

    import java.net.Socket;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.io.BufferedReader;

    public class MyClient {
      private int port;
      private Socket socket;

      public MyClient(String host, int port) throws IOException {
        socket = new Socket(host, port);
      }
      public MyClient(int port) throws IOException {
        this("localhost", port);
      }
      public MyClient() throws IOException {
        this("localhost", 10005);
      }

      public void talk() {
        try {
          BufferedReader localReader = new BufferedReader(
          new InputStreamReader(System.in));
          BufferedReader reader = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));
          PrintWriter writer = new PrintWriter(socket.getOutputStream());

          String msg = null;
          while((msg = localReader.readLine()) != null) {
        writer.println(msg);
        wirter.flush();
        System.out.println(reader.readLine());
        if (msg.equals("bye")) break;
          }
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          try {
        if (socket != null) socket.close();
          } catch (IOException e) {
        e.printStackTrace();
          }
        }
      }

      public static void main(String[] args) throws IOException {
        new MyClient().talk();
      }

}

Ошибка сказала:

at MyServer.main(MyServer.java:41)
java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(Unknown Source)
    at MyServer.serve(MyServer.java:26)
    at MyServer.main(MyServer.java:41)

Но я действительно не могу найти ошибку. Пожалуйста, дайте мне подсказку.

3 ответа

В вашем блоке finally, который находится внутри цикла, вы закрываете сокет сервера:

try {
        socket = sSocket.accept();
        new MyThread(socket).start();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (sSocket != null)
                sSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Измените свой код на:

try {
        socket = sSocket.accept();
        new MyThread(socket).start();
    } catch (IOException e) {
        try {
            if (sSocket != null)
                sSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    } 

Когда вы запускаете серверную программу, она блокируется в этой строке:

socket = sSocket.accept();

Затем вы запускаете клиентскую программу, которая сразу подключается к серверу (new MyClient()) и блокирует ожидание пользовательского ввода с консоли:

BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
while((msg = localReader.readLine()) != null) {

Когда вы подключили клиента к серверу, сервер запустил новый поток:

new MyThread(socket).start();

который заблокировал ожидание клиентского ввода (пользовательский ввод на консоли с другой стороны сокета):

BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((msg = reader.readLine()) != null) {

Но после создания нового потока для обработки клиентского запроса ваш сервер закрывает sSocket, а затем пытается принять в том же закрытом сокете, отсюда и исключение. Если вы переписываете свой код следующим образом:

  public void serve() {
    Socket socket = null;
    while (true) {
        try {
            System.out.println("1 "+System.currentTimeMillis());
            socket = sSocket.accept();
            System.out.println("2 "+System.currentTimeMillis());
            new MyThread(socket).start();
            System.out.println("3 "+System.currentTimeMillis());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                System.out.println("4 "+System.currentTimeMillis());
                if (sSocket != null) {
                    System.out.println("5 "+System.currentTimeMillis());
                    sSocket.close();                        
                }
                System.out.println("6 "+System.currentTimeMillis());
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

Вы увидите следующий вывод:

1 1370944252112
2 1370944260482
3 1370944260487
4 1370944260487
5 1370944260487
6 1370944260487
1 1370944260487
4 1370944260488
5 1370944260488
6 1370944260488
1 1370944260488
4 1370944260488
5 1370944260488
6 1370944260488

Это означает, что ваш сервер находится в бесконечном цикле, постоянно выдавая исключение. Чтобы решить проблему бесконечного цикла, смотрите ответ @ gma.

Если вы запускаете сервер в режиме отладки и ставите точку останова в этой строке:

  socket = sSocket.accept();        

а затем запустите клиент, введите то, что вы хотите, и нажмите Enter, вернитесь на сервер и перешагните через него, вы увидите (только) первое переданное сообщение - похоже, вы не хотели, чтобы оно так себя вели, но это другая проблема.

Я настоятельно рекомендую вам внимательно прочитать официальное руководство по сокетам Java.

Вы не должны закрывать свой serverSocket внутри цикла. Поместите цикл while в блок try.

Другие вопросы по тегам