Java 文件结束异常



我正在使用JavaFX编写一个简单的即时消息程序,遇到了文件结束异常,经过数小时的调试,我找不到解决方案。

我的程序分为两部分,客户端和服务器。它们相互发送序列化对象,其中包含完成所需操作所需的所有必要信息。当我开始在服务器中收到此错误时,我正在向我的程序添加其他功能。此后,我删除了所有其他代码,但仍然收到此错误消息。我不明白为什么我会收到此错误,因为客户端和服务器都没有发送消息,这意味着没有文件可以到达末尾?

我注释掉了我调用方法"sendMessage()"的行,这似乎解决了问题,但我需要这种方法才能工作。

波纹管是服务器类的副本

package instachatfx.server;

public class ServerMain {
private static HashSet<ObjectOutputStream> writers;
private static ArrayList<User> users = new ArrayList<>();
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
writers = new HashSet<>();
try (ServerSocket listener = new ServerSocket(Constants.
while (true) {
new Handler(listener.accept()).start();
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static class Handler extends Thread {
private Socket socket;
private ObjectInputStream input;
private OutputStream os;
private ObjectOutputStream output;
private InputStream is;
private User user;
private String code;
public Handler(Socket socket) throws IOException {
this.socket = socket;
}
@Override
public void run() {
try {
is = socket.getInputStream();
input = new ObjectInputStream(is);
os = socket.getOutputStream();
output = new ObjectOutputStream(os);
while (socket.isConnected()) {
System.out.println("Waiting for packet...");
Packet inputmsg = (Packet) input.readObject();
if (inputmsg != null) {
switch (inputmsg.getHeader()) {
case REGISTER:
System.out.println("Case: REGISTER");
registerUser((User) inputmsg.getContent());
break;
case LOGIN:
System.out.println("Case: LOGIN");
loginUser((User) inputmsg.getContent());
break;
case CODE:
System.out.println("Case: CODE");
if (((String) inputmsg.getContent()).equalsIgnoreCase(code)) {
Constants.getDBManager().createNewUser(user);
loginUser(user);
} else {
sendMessage(PacketHeader.INCORRECT_CODE, "Incorrect code");
}
break;
case MESSAGE:
System.out.println("Case: MESSAGE");
sendToAll(inputmsg);
System.out.println(((Message) inputmsg.getContent()).getUser().toString() + ": " + ((Message) inputmsg.getContent()).getContent());
break;
default:
throw new HeaderNotFoundException("Server has no case for: " + inputmsg.getHeader().name());
}
}
}
} catch (SocketException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (HeaderNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (EOFException ex)
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} finally {
closeConnections();
}
}
private void sendToAll(Packet msg) throws IOException {
System.out.println("Send to all: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
private void sendToOthers(Packet msg) throws IOException {
System.out.println("Send to others: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
if (output != writer) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
}
/**
* Logs in a user
* @param u the user to be logged in
*/
private void loginUser(User u) {
try {
User us;
if ((us = Constants.getDBManager().loginUser(u)) != null) {
System.out.println("User found in database");
user = us;
writers.add(output);
users.add(user);
LoginMsg msg = new LoginMsg(user, users);
sendMessage(PacketHeader.LOGIN_SUCCESSFUL, 
sendToOthers(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has joined the chat", new User("SERVER", null))));
} else {
sendMessage(PacketHeader.LOGIN_FAIL, "Please check email and password");
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void registerUser(User u) throws IOException{
user = u;
if (Constants.getDBManager().checkDeuplicateEmail(u.getEmail())) {
sendMessage(PacketHeader.EMAIL_ALREADY_USED, "The email address " + u.getEmail() + " has already been used to make an account");
System.out.println("Email already exists");
return;
} else if ((code = sendVerificationEmail(u)) == null) {
sendMessage(PacketHeader.EMAIL_NOT_VALID, "There was an error sending the email  to "
+ u.getEmail() + ". Please make sure the email is correct");
System.out.println("email failed sending");
return;
}
sendMessage(PacketHeader.WAIT_FOR_CODE, "Type in code in email");
}
/**
* Sends an email to the user to verify that it is correct
*
* @param u The user to send the email to
* @return null - the email failed sending <br>
* random sting - the email successfully sent using this verification
* code
*/
private String sendVerificationEmail(User u) {
String code = RandomString.getAlphaNumericString(10);
if (Constants.getSendEmail().sendEmail(u, code)) {
return code;
}
return null;
}
/**
* Sends a packet to only the client
*
* @param packetHeader for the client to tell how to read in the message
* @param msg the message for the client
*/
private void sendMessage(PacketHeader packetHeader, Object msg) throws IOException {
System.out.println("Send to client: " + packetHeader);
Packet message = new Packet(packetHeader, msg);
//ERROR OCCURS HERE
output.writeObject(message);
output.flush();
}
private void closeConnections() {
if (user != null){
users.remove(user);
}
try {
sendToAll(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has left the chat", new User("SERVER", null))));
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
if (output != null){
writers.remove(output);
}
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (os != null){
try {
os.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (input != null) {
try {
input.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}

编辑:这是堆栈跟踪

2019-11-11下午01:44:21 instachatfx.server.ServerMain$Handler run SEVERE:空 java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2950) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1534) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427) at instachatfx.server.ServerMain$Handler.run(ServerMain.java:83)

我不明白为什么我会收到此错误...

您收到错误是因为一端已关闭其输出流...或整个套接字。 这可能是显式关闭的结果,也可能是因为应用程序已退出。

。由于客户端和服务器都没有发送消息...

应用程序(客户端或服务器)正在尝试读取消息,但不会有消息出现,因为另一端已关闭此端尝试从中读取的流。

。这意味着没有文件可以到达末尾。

你的逻辑不正确。 引用的"文件"是上面提到的流。 如果关闭写入端,如果读取端尝试继续读取,则会看到流结束/文件结束。


看起来伪匿名评论者已经发现了一个可能解释您的问题的错误。Socket.isConnected()方法不能用于测试套接字是否仍处于连接状态。 javadoc 指出:

public boolean isConnected()

返回套接字的连接状态。

注意:关闭套接字不会清除其连接状态,这意味着 此方法对于闭合的套接字返回 true(请参阅isClosed()如果 它在关闭之前已成功连接

返回:true套接字是否已成功连接到服务器

(强调后加...


如果您需要更多帮助,请提供一个适当的最小可重现示例,并确保包含一个或多个异常的完整堆栈跟踪。

最新更新