Question

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.

Était-ce utile?

La 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
}

Autres conseils

I want to be able to retrieve/send serializable files, while also being able to retrieve/send messages from the user.

You can do all that with an ObjectInputStream and ObjectOutputStream.

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

That statement is meaningless until you specify the 'conflict'.

I've tried using two streams for the same socket (Data*Stream & Object*Stream)

  1. You can't do that. Use the same stream for the life of the socket.

  2. You don't need to do that. Anything you can do with a Data*Stream you can do with an Object*Stream, because Data*Stream implements Data*Put and Object*Stream implements Object*Put, and Object*Put extends Data*Put.

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.

That means you closed the stream and continued to use it. This is caused by your use of two streams. Closing any stream wrapped around a socket input or output stream closes the other stream and the socket. You don't need this.

(only happens right when I send the message)

It only happens when you read from or write to a stream that is already closed.

Can someone point me in the right direction to how I would approach retrieving 2 different types of information through a stream?

Just use the API of Object*Stream.

(without taking an easy way out. I don't wanna have to do writeObject("[message]"+input); or any cheap tricks like that.

I have no idea why you consider that a 'cheap trick'. You need to stop making assumptions and start designing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top