这是代码,我认为它们没问题,但JRE并不这么认为

时间:2013-06-11 09:02:17

标签: java exception socketexception

以下是服务器的代码

    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)

但我真的找不到这个bug。请给我一个提示。

3 个答案:

答案 0 :(得分:1)

循环的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();
        }
    } 

答案 1 :(得分:0)

您不应该在循环内关闭serverSocket。将while循环放在try块中。

答案 2 :(得分:0)

启动服务器程序时,它会在此行上阻止:

socket = sSocket.accept();

然后启动客户端程序,将immediatley连接到服务器(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,然后在同一个关闭的套接字上尝试accept,因此异常。如果您重写代码如下:

  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();        

然后启动客户端,输入您想要的内容并按回车键,返回服务器并跳过,您将看到(仅)传输的第一条消息 - 看起来您不希望它表现得那样,但这是另一个问题。

我强烈建议您仔细阅读认真官方Java socket tutorial