java.io.EOFException 从套接字读取时
java.io.EOFException when reading from socket
我以这种方式设置了一个服务器和一个客户端。我找不到 EOFException 的原因,因为它是随机发生的。每次客户端连接时都会抛出以下异常,但我无法弄清楚它的来源。它总是在读取客户端发送的内容之前发生。例外总是在这一行:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
例外情况:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End.run(End.java:62)
at com.denesgarda.Socketeer.data.End.run(End.java:76)
at com.denesgarda.Socketeer.data.End.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
这是我的服务器代码:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
这是我的客户端代码:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
我试过的
我以前曾多次尝试解决这个问题。我试图创建对象输出流。我已经切换了初始化对象输入流和对象输出流的顺序。这样服务器就不会与客户端陷入僵局。我不知道是什么导致了这个错误。
我认为我知道这里发生了什么,但我不能确定,因为你的代码是零散的,而且症状没有很好的表征。 (例如,例外不太可能真的是随机的。)
首先有一个不争的事实。连接的一侧看到 EOFException
因为另一侧已关闭网络连接。这就是那个例外的意思。
在您的情况下,服务器在 ObjectInputStream
构造函数中获取异常,因为构造函数试图读取客户端从未发送的 object 流 header ...那种联系。
现在,理论。我想我知道为什么。这是您代码的相关部分(为简洁起见,删除了一些位)。
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
注意有两个插座!第一个被创建并传递给关闭挂钩。第二个在 send
内创建和使用,然后关闭。
我觉得是第一个Socket的问题。创建后,它会建立与服务器的连接。服务器代码将 accept
它然后尝试读取。读取将阻塞...因为客户端尚未向 that 套接字写入任何内容。然后客户端将调用 send
打开并使用不同的套接字。
最终,客户端应用程序退出。
当它退出时,关闭钩子关闭第一个套接字。这会导致服务器端看到流的结尾...并触发 EOFException
.
那么如何解决这个问题?
这更取决于“大局”。 真正的客户端是向服务器发送单条消息,还是需要重用socket发送多条消息?
假设是前者,解决方法很简单:
删除创建套接字并将其传递给关闭挂钩的代码。如您所写,它没有 有用的 目的。
重写 send
方法以使用 try with resources;例如
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
请注意,以上将按正确顺序自动关闭 3 个资源。
我以这种方式设置了一个服务器和一个客户端。我找不到 EOFException 的原因,因为它是随机发生的。每次客户端连接时都会抛出以下异常,但我无法弄清楚它的来源。它总是在读取客户端发送的内容之前发生。例外总是在这一行:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
例外情况:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End.run(End.java:62)
at com.denesgarda.Socketeer.data.End.run(End.java:76)
at com.denesgarda.Socketeer.data.End.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
这是我的服务器代码:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
这是我的客户端代码:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
我试过的
我以前曾多次尝试解决这个问题。我试图创建对象输出流。我已经切换了初始化对象输入流和对象输出流的顺序。这样服务器就不会与客户端陷入僵局。我不知道是什么导致了这个错误。
我认为我知道这里发生了什么,但我不能确定,因为你的代码是零散的,而且症状没有很好的表征。 (例如,例外不太可能真的是随机的。)
首先有一个不争的事实。连接的一侧看到 EOFException
因为另一侧已关闭网络连接。这就是那个例外的意思。
在您的情况下,服务器在 ObjectInputStream
构造函数中获取异常,因为构造函数试图读取客户端从未发送的 object 流 header ...那种联系。
现在,理论。我想我知道为什么。这是您代码的相关部分(为简洁起见,删除了一些位)。
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
注意有两个插座!第一个被创建并传递给关闭挂钩。第二个在 send
内创建和使用,然后关闭。
我觉得是第一个Socket的问题。创建后,它会建立与服务器的连接。服务器代码将 accept
它然后尝试读取。读取将阻塞...因为客户端尚未向 that 套接字写入任何内容。然后客户端将调用 send
打开并使用不同的套接字。
最终,客户端应用程序退出。
当它退出时,关闭钩子关闭第一个套接字。这会导致服务器端看到流的结尾...并触发 EOFException
.
那么如何解决这个问题?
这更取决于“大局”。 真正的客户端是向服务器发送单条消息,还是需要重用socket发送多条消息?
假设是前者,解决方法很简单:
删除创建套接字并将其传递给关闭挂钩的代码。如您所写,它没有 有用的 目的。
重写
send
方法以使用 try with resources;例如public void send(Object object) throws IOException { try (Socket socket = new Socket(THAT.getAddress(), this.port); OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os)) { oos.writeObject(object); } }
请注意,以上将按正确顺序自动关闭 3 个资源。