mike
mike

Reputation: 1338

Client/Server; Server throws EOFException after Client code complete

I am trying to set up a simple Client/Server model where is send an object via a DataInput/OutputStream. My Client code is:

public static void main(String[] args) {
    final String HOST_NAME = "localhost"; 
    final int PORT_NUMBER = 9090;

    Card card = new Card(0, 0, 0, 0);

    try {
        Socket socket = new Socket(HOST_NAME, PORT_NUMBER);
        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());

        output.writeObject(card);
        card = new Card(1, 1, 1, 1);
        output.writeObject(card);
        output.writeObject(null);

        output.close();
        input.close();
        socket.close();
    } catch (UnknownHostException e) {
        System.err.println("Can not recognize: " + HOST_NAME);
    } catch (IOException e) {
        System.err.println("Bad port number: " + PORT_NUMBER);
    }
}

On the Server side, I have tried several variations of code, the current one looks like this:

static boolean listening = true;

public static void main(String args[]) throws IOException {
    ServerSocket serverSocket = new ServerSocket(9090);
    while (listening) {
        Socket socket = serverSocket.accept();
        try {
            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());

            while ((card = (Card) input.readObject()) != null) {
                for (int feature : card.getFeatures()) {
                    System.out.println(feature + " ");
                }
            }

            output.close();
            input.close();
            socket.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This is a simplified and working version of what I want. I want the server to keep listening for new Card objects and printing their features until it gets a null object. However, what happens when I run this is that the features of the first card are printed then I immediately get an EOFException on the server end.

I've tried different variations of the above, including using a finally to break out of the while, but in every case I never make it past printing the first card. How can I guarantee that the server will keep listening and receiving cards until the Client closes the socket?

Upvotes: 0

Views: 460

Answers (1)

user207421
user207421

Reputation: 310860

while ((card = (Card) input.readObject()) != null) {

Unless you're planning on sending yourself a null to terminate this loop, this isn't a valid way to read an ObjectInputStream. The readObject() method doesn't return null at end of stream: it throws EOFException. So, you have to catch it. So the loop condition should really be while (true), and the readObject() call needs to be inside the loop. Then you either have to have

try
{
    card = (Card)input.readObject();
    // ...
}
catch (EOFException)
{
    break;
}

inside the loop, or have the loop inside a try/catch block with a catch (EOFException) which now doesn't need a break;.

Upvotes: 1

Related Questions