Thufir
Thufir

Reputation: 8487

why doesn't the server receive the object sent from the client?

How do I handle the ObjectOutputStream and ObjectInputStream so that the Server instance correctly logs the received Object. Currently, it never gets that far. Each time the client runs, the server "waits for data", but never seems to actually receive it.

server:

package net.bounceme.dur.driver;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Server {

    private static final Logger log = Logger.getLogger(Server.class.getName());
    private final RecordQueue recordsQueue = new RecordQueue();

    public static void main(String[] args) {
        Properties props = PropertiesReader.getProps();
        int portNumber = Integer.parseInt(props.getProperty("port"));

        while (true) {
            try {
                new Server().inOut(portNumber);
            } catch (java.net.SocketException se) {
                Logger.getLogger(Server.class.getName()).log(Level.FINE, "spammy", se);
            } catch (IOException ioe) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ioe);
            } catch (ClassNotFoundException cnf) {
                Logger.getLogger(Server.class.getName()).log(Level.INFO, null, cnf);
            }
        }
    }


    public void inOut(int portNumber) throws IOException, ClassNotFoundException {
        ServerSocket serverSocket = new ServerSocket(portNumber);
        Socket socket = serverSocket.accept();
        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        log.info("...connected...waiting for data...");
        MyRecord recordFromClient = (MyRecord) objectInputStream.readObject();
        objectOutputStream.writeObject(recordFromClient);
        objectOutputStream.flush();
        objectInputStream.close();
        objectOutputStream.close();
        log.info(recordFromClient.toString());//never logs
        System.out.println("never gets here");
    }
}

Each time the client runs, the server waits for data, but, at least according to the output below, never receives it.

thufir@dur:~$ 
thufir@dur:~$ java -jar NetBeansProjects/Server/dist/Server.jar 
Jun 29, 2014 9:28:45 PM net.bounceme.dur.driver.Server inOut
INFO: ...connected...waiting for data...
Jun 29, 2014 9:28:46 PM net.bounceme.dur.driver.Server inOut
INFO: ...connected...waiting for data...

client code:

package net.bounceme.dur.driver;

import java.net.*;
import java.io.*;
import java.util.Properties;
import java.util.logging.Logger;

public class Client {

    private static final Logger log = Logger.getLogger(Client.class.getName());

    public void put(String server, int portNumber, Socket socket, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
        socket = new Socket(server, portNumber);
        objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        MyRecord record = new MyRecord(1, "foo");
        objectOutputStream.writeObject(record);
        objectOutputStream.flush();
        objectOutputStream.close();
    }

    public static void main(String args[]) throws IOException, ClassNotFoundException {
        Properties props = PropertiesReader.getProps();
        int portNumber = Integer.parseInt(props.getProperty("port"));
        String server = (props.getProperty("server"));
        Socket socket = null;
        ObjectOutputStream objectOutputStream = null;
        ObjectInputStream objectInputStream = null;
        new Client().put(server, portNumber, socket, objectOutputStream);
    }
}

Upvotes: 0

Views: 160

Answers (1)

laune
laune

Reputation: 31290

Client and Server must agree with each other not only about how they send data but also when to close a socket. A unilateral close of a socket will close the connection and thwart the reception even of data that has already been sent. And I think that's what's happening here.

Client code:

    objectOutputStream.writeObject(record);
    objectOutputStream.flush();
    objectOutputStream.close();

This is executed without interruption and so the socket is closed as soon as the last byte has been sent on the wire. Thus, the server's reply cannot be sent.

Server code:

    MyRecord recordFromClient = (MyRecord) objectInputStream.readObject();
    objectOutputStream.writeObject(recordFromClient);

Clearly, reception happens a little later than sending, and so the server blocks.

Keep the socket open from both sides until the client has received; then he may close the socket. The server should see an end-of-file when trying to read again, and can close accordingly. (More elaborate handshaking is possible, of course.)

Later

To corroberate, simply add a Thread.sleep(2000); between Client's flush and close - and the Server will indeed "get here".

Upvotes: 2

Related Questions