EOFException through by ObjectInputStream.readObject()

I have a client-server application and I send messages between them by using a BufferedReader and PrintWriter to send the text and ObjectInputStream and ObjectOutputStream to send an enum type representing the type of message. Both the client and the server make threads that listen for incoming messages and handle them appropriately. I assume that both ObjectInputStream.readObject() and BufferedReader.readLine() block until there is something actually in the stream, otherwise my approach is probably wrong. Sometimes, but not always, when the client connects to the server, the ObjectInputStream on the server throws an EOFException and I'm not sure why this is happening. Some other thread I read suggested including ObjectOutputStream.flush() on the client side, but this didn't seem to fix the problem. I'm not sure if I should still inlucde flush() and where (for ObjectOutputStream only or for ObjectInputStream as well?). The relevant code snippets are shown below:

Server code:

privatevoid processMessage(MessageType type, String input){

String user, pass;

try{

switch(type){

case Create:

user = input.substring(0, input.indexOf(" "));

input = input.substring(input.indexOf(" ")+1);

pass = input;

client.getObjectOut().writeObject(MessageType.Create);

if(LostHavenServer.registered.containsKey(user))

client.getWriter().println("Username already exists");

else{

LostHavenServer.registered.put(user,new Player(user, pass));

client.getWriter().println("Account created successfully");

}

closeConnection();

break;

case Login:

user = input.substring(0, input.indexOf(" "));

input = input.substring(input.indexOf(" ")+1);

pass = input;

client.getObjectOut().writeObject(MessageType.Login);

if(!LostHavenServer.registered.containsKey(user))

client.getWriter().println("No such player exists");

elseif(!LostHavenServer.registered.get(user).getPass().equals(pass))

client.getWriter().println("Incorrect password");

elseif(LostHavenServer.loggedOn.containsKey(user))

client.getWriter().println("This player is already logged on");

else{

client.getWriter().println("Login successful");

}

}

}catch(IOException ioe){

ioe.printStackTrace();

}

}

publicvoid run(){

try{

while(true){

processMessage((MessageType)objIn.readObject(), in.readLine());

}

}catch(ClassNotFoundException cnfe){

cnfe.printStackTrace();

}catch(SocketException se){

if(!terminated)

System.out.println("the client disconnected");

}catch(IOException ioe){

ioe.printStackTrace();

}

}

Client code:

publicvoid sendMessage(MessageType type, String input){

System.out.println("message started");

try{

objOut.writeObject(type);

out.println(input);

}catch(IOException ioe){

ioe.printStackTrace();

}

System.out.println("message ended");

}

publicvoid run(){

try{

while(connected){

main.processMessage((MessageType)objIn.readObject(), in.readLine());

}

}catch(ClassNotFoundException cnfe){

cnfe.printStackTrace();

}catch(SocketException se){

if(!terminated){

System.out.println("the server disconnected");

}

}catch(IOException ioe){

ioe.printStackTrace();

}

}

[6271 byte] By [Japhetha] at [2007-11-27 5:17:32]
# 1

> I assume that both ObjectInputStream.readObject() and BufferedReader.readLine() block until there is something actually in the stream

Correct.

> I'm not sure if I should still inlucde flush() and where (for ObjectOutputStream only or for ObjectInputStream as well?).

ObjectInputStream doesn't have a flush() method.

Your code looks like you are using two output streams on the same socket to send, and two input streams to receive. If any of those is buffered that isn't going to work, because the buffers will steal data from each other, and ObjectOutputStream, ObjectInputStream, BufferedReader, and BufferedWriter, and PrintWriter are all buffered. Don't send and receive lines as well as objects: send all the data as objects.

ejpa at 2007-7-12 10:40:23 > top of Java-index,Core,Core APIs...
# 2

I made the changes you suggested and it seems that the error occurs less often, but still occurs. The exact error is

java.io.EOFException

at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)

at java.io.ObjectInputStream.readObject0(Unknown Source)

at java.io.ObjectInputStream.readObject(Unknown Source)

at ServerThread.run(ServerThread.java:93)

Should I post more code or the code that I changed? Also, I tried using objOut.flush() after I call writeObject(), but that didn't help. Is there any place I should be using objOut.flush()?

It seems that the eofexception occurs when I disconnect and try to connect again very quickly. Maybe I should have the client check that it "fully disconnected" before trying to connect again.

Message was edited by:

Japheth

Japhetha at 2007-7-12 10:40:23 > top of Java-index,Core,Core APIs...
# 3
You could post some more code. Of course if you ever get an EOFException, or any IOException for that matter, when reading a socket there is nothing for it but to close the socket, and I don't see your code doing that.
ejpa at 2007-7-12 10:40:23 > top of Java-index,Core,Core APIs...
# 4
I switched to just sending strings since I realized sending enums as strings was actually really easy. It all works now and thanks for your help ejp.
Japhetha at 2007-7-12 10:40:23 > top of Java-index,Core,Core APIs...
# 5
You can send enums as enums of course.
ejpa at 2007-7-12 10:40:23 > top of Java-index,Core,Core APIs...