Search code examples
javasocketsstreamobjectinputstreamobjectoutputstream

Sorting data received through ObjectInputStream


I made a messenger that receives data from a server through a ObjectInputStream. I want to be able to retrieve/send serializable files, while also being able to retrieve/send messages from the user.

I couldn't find a good way to sort between the two (Objects and Messages) without causing conflict with messaging.

I've tried using two streams for the same socket (Data*Stream & Object*Stream), and it seems to establish fine, but when I try sending a message from the server to the client through Data*Stream, I get java.net.SocketException: socket closed on my client. (only happens right when I send the message)

Can someone point me in the right direction to how I would approach retrieving 2 different types of information through a stream? (without taking an easy way out. I don't wanna have to do writeObject("[message]"+input); or any cheap tricks like that.



(EDIT) SOLUTION:

Thanks to janos, he has inspired me to write this code. :') Thanks man

The Input receiver:

protected Object data;

public synchronized Object receivedData() throws ClassNotFoundException,
                                                 IOException {
    data = in.readObject();

    if(!(data instanceof String)) {
        retrieveObject();
        data = "";
        System.out.println("Object");
    }
    return data;
}

And the messaging thread:

ExecutorService pool = Executors.newScheduledThreadPool(1);

private Runnable receiveData;
public void receiveData() {
    receiveData = new Runnable() {

        public void run() {
            String input;
            try {
                while((input = (String) receivedData()) != null) {
                    if(input.length() > 1) 
                        System.out.println(input);

                }
            }catch(IOException | ClassNotFoundException e){ e.printStackTrace();}
        }
    };

    pool.execute(receiveData);
}

If you have any improving tips, please let me know and I'll update this code.


Solution

  • You can create a parent class Message, and sub-classes DataMessage and TextMessage.

    When receiving a Message, you can check with instanceof its underlying type, and handle it accordingly.

    These *Message classes could wrap any objects you want to pass between client and server in their member variables. The *Message classes would have to be serializable, consequently all member variables must be serializable too.

    For example given these Message types:

    class Message {}
    
    class TextMessage extends Message {
        String text;
    }
    
    class DataMessage extends Message {
        User user;
    }
    

    You can handle received messages like:

    Message message = (Message) in.readObject();
    if (message instanceof TextMessage) {
        // do something with ((TextMessage)message).text
    } else if (message instanceof DataMessage) {
        // do something with ((DataMessage)message).user
    }