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 不会做任何事情,反之亦然。
它关闭套接字。此外,serverMsg
或 clientMsg
的值变为“关闭”。所以另一个线程将进入if
和break
。以上是关于Java IOException 流在服务器客户端程序中关闭的主要内容,如果未能解决你的问题,请参考以下文章
java.io.IOException: 您的主机中的软件中止了一个已建立的连接
java.io.IOException: 远程主机强迫关闭了一个现有的连接。
为啥新的 Java 8 流在 toArray 调用上返回一个对象数组?
netty之IOException Connection timed out?