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

Posted

技术标签:

【中文标题】Java IOException 流在服务器客户端程序中关闭【英文标题】:Java IOException Stream Closed in Server Client program 【发布时间】:2019-12-24 01:53:14 【问题描述】:

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

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: 流关闭 在 java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:176) 在 java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:342) 在 java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) 在 java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) 在 java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) 在 java.base/java.io.InputStreamReader.read(InputStreamReader.java:185) 在 java.base/java.io.BufferedReader.fill(BufferedReader.java:161) 在 java.base/java.io.BufferedReader.readLine(BufferedReader.java:326) 在 java.base/java.io.BufferedReader.readLine(BufferedReader.java:392) 在 Q2Server.run(Q2Server.java:65) 在 java.base/java.lang.Thread.run(Thread.java:835)

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

【问题讨论】:

您已共享状态但没有同步。这段代码的编写方式非常混乱。 【参考方案1】:

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

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

希望这会有所帮助。

【讨论】:

我这样做了,现在我没有收到错误。但是在服务器向客户端发送“关闭”后,服务器断开连接,但客户端在关闭之前再接受一次输入。当客户端发送“关闭”时也会发生同样的情况,服务器会在关闭之前再输入一个。 @ShantanuShinde 是的,我也注意到了。这只是您编写代码的方式。调试器可以帮助您自己查看这一点,并可能修复此行为。 我试过了,即使在第一个线程关闭后,另一个线程也会继续执行。我该如何解决?我放了一个 if 语句,但它似乎在 if 内部切换。 @ShantanuShinde 这种结构的意义何在? if(serverMsg.equals("close")) break; 当客户端从服务器收到关闭命令时,您的 porgram 不会做任何事情,反之亦然。 它关闭套接字。此外,serverMsgclientMsg 的值变为“关闭”。所以另一个线程将进入ifbreak

以上是关于Java IOException 流在服务器客户端程序中关闭的主要内容,如果未能解决你的问题,请参考以下文章

java.io.IOException: 您的主机中的软件中止了一个已建立的连接

java.io.IOException: 远程主机强迫关闭了一个现有的连接。

为啥新的 Java 8 流在 toArray 调用上返回一个对象数组?

netty之IOException Connection timed out?

Java HttpURLConnection.getInputStream 但得到 401 IOException

JAVA的程序java.io.IOException出错是啥??