Java IOException 流在服务器客户端程序中关闭

Java IOException Stream Closed in Server Client program

我正在尝试制作一个服务器客户端程序,允许在不等待响应的情况下从服务器向客户端发送多条消息,反之亦然。当第一个客户端连接和断开连接时,该程序工作正常。但是当我再次连接客户端时,我得到了错误。这是我的服务器代码:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import java.io.InputStreamReader;

import java.io.BufferedReader;

class Q2Server implements Runnable{
    private ServerSocket serverSocket;
    private Socket socket;
    private DataOutputStream out;
    private BufferedReader in1;
    private DataInputStream in2;
    private Thread read, write;
    private String clientMsg, serverMsg;

    public Q2Server (int port) throws IOException{
        serverSocket = new ServerSocket(port);

        while(true) {
            try {
                System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
                socket = serverSocket.accept();

                System.out.println("Just connected to " + socket.getRemoteSocketAddress());

                out = new DataOutputStream(socket.getOutputStream());
                out.writeUTF("Thanks for connecting to " + socket.getLocalSocketAddress());

                clientMsg = "";
                serverMsg = "";

                read = new Thread(this);
                write = new Thread(this);

                read.start();
                write.start();

                read.join();
                write.join();

            } catch(IOException e) {
                e.printStackTrace();
            } catch(InterruptedException ie) {
                ie.printStackTrace();
            }
        }

    }

    public void run () {
        try {
            if(Thread.currentThread() == write) {
                while(true) {
                    try {
                        if(clientMsg.equals("close")) {
                            break;
                        } else {
                            in1 = new BufferedReader(new InputStreamReader(System.in));
                            out = new DataOutputStream(socket.getOutputStream());
                            serverMsg = in1.readLine();
                            out.writeUTF(serverMsg);
                            if(serverMsg.equals("close")) {
                                socket.close();
                                in1.close();
                                in2.close();
                                out.close();
                                System.out.println("Closing connection...");
                                break;
                            }    
                        }
                    } catch (SocketException s) {
                        break;
                    } 

                } 

            } else {
                while(true) {
                    try {
                        if(serverMsg.equals("close")) {
                            break;
                        }
                        in2 = new DataInputStream(socket.getInputStream());
                        clientMsg = in2.readUTF();
                        System.out.println("Client: " + clientMsg);
                        if(clientMsg.equals("close")) {
                            socket.close();
                            in1.close();
                            in2.close();
                            out.close();
                            System.out.println("Closing connection...");
                            break;
                        }
                    } catch(SocketException s) {
                        break;
                    } 

                } 

            }
        } catch (IOException i) {
            i.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        Q2Server server = new Q2Server(8080);
    }
}

客户代码:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.rmi.UnexpectedException;


import java.io.InputStreamReader;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.lang.Thread;

class Q2Client implements Runnable {
    private Socket socket;
    private Thread read, write;
    private BufferedReader in1;
    private DataInputStream in2;
    private DataOutputStream out;
    private String clientMsg, serverMsg;

    public Q2Client(int port) {
        try {
            socket = new Socket("localHost",port);
            System.out.println("Connected to port: " + port);

            clientMsg = serverMsg = "";

            read = new Thread(this);
            write = new Thread(this);

            in2 = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

            System.out.println(in2.readUTF());

            read.start();
            write.start();

            read.join();
            write.join();

        } catch(UnexpectedException u) {
            u.printStackTrace();
        } catch(IOException i) {
            i.printStackTrace();
        } catch(InterruptedException ie) {
            ie.printStackTrace();
        }
    }

    public void run() {
        try {
            if(Thread.currentThread() == write) {
                while(true) {
                    try {
                        if(serverMsg.equals("close")) {
                            break;
                        }
                        in1 = new BufferedReader(new InputStreamReader(System.in));
                        out = new DataOutputStream(socket.getOutputStream());
                        clientMsg = in1.readLine();
                        out.writeUTF(clientMsg);
                        if(clientMsg.equals("close")) {
                            socket.close();
                            in1.close();
                            in2.close();
                            out.close();
                            System.out.println("Closing connection...");
                            break;
                        }
                    } catch (SocketException s) {
                        break;
                    } 

                } 
            } else {
                while(true) {
                    try {
                        if(clientMsg.equals("close")) {
                            break;
                        }
                        in2 = new DataInputStream(socket.getInputStream());
                        serverMsg = in2.readUTF();
                        System.out.println("Server: " + serverMsg);
                        if(serverMsg.equals("close")) {
                            socket.close();
                            in1.close();
                            in2.close();
                            out.close();
                            System.out.println("Closing connection...");
                            break;
                        }
                    } catch (SocketException s) {
                        break;
                    }

                } 
            }
        } catch (IOException i) {
            i.printStackTrace();
        }

    }

    public static void main(String[] args) {
        Q2Client client = new Q2Client(8080);
    }
}

这是异常的堆栈跟踪:

java.io.IOException: Stream closed at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:176) at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:342) at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185) at java.base/java.io.BufferedReader.fill(BufferedReader.java:161) at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326) at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392) at Q2Server.run(Q2Server.java:65) at java.base/java.lang.Thread.run(Thread.java:835)

当服务器或客户端发送 "close" 时,连接关闭。客户端可以再次连接。但是当我再次 运行 客户端代码时,我得到了异常。出了什么问题,我该如何解决?

您遇到异常是因为您试图从不再存在的 BufferedReader 中读取数据,尤其是 in1。在第一个 运行 时,您所有的流和阅读器都按应有的方式打开,但是在从客户端收到命令 close 后,您的服务器关闭了 in1。然后,当客户端尝试重新连接时,程序会尝试将 in1.readLine() 的值分配给 serverMsg,这是一个 String,但由于 in1 已不复存在,因此 IOException 发生是因为 BufferedReader 已关闭并且无法从中读取任何内容。

我想既然你想离开服务器 运行ning 而客户端可以在任何给定时间连接和断开连接,这完全有道理,也许你不应该关闭 BufferedReader 在您的情况下向服务器提供键盘命令。关闭它对我来说没有意义,因为当客户端断开连接时你并没有停止整个服务器,你只是关闭连接,但服务器仍然应该能够接受命令。

希望对您有所帮助。