2

I have a couple of classes. Student, Teacher and Book.

I want to send instances of those 3 objects from server to the connecting client. I know how to send/receive instances of single type, i.e. Student from server to client using the following code

Client Side

            Socket socket = new Socket(ip, port);
        try {
            ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
            try {
                Object object =(Student) objectInput.readObject();
                Student std = (Student) object;
                //do something with std
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }          

Server Side

        Student a = new Student();
        ServerSocket myServerSocket = new ServerSocket(port);
        Socket skt = myServerSocket.accept();   
        try 
        {
            ObjectOutputStream objectOutput = new ObjectOutputStream(skt.getOutputStream());
            objectOutput.writeObject(a);                
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        } 

How to extend this code to be able to send different types of objects from server and receive them correctly on the client side

Do I need to wrap them all in another object and give each one a type? Thanks!

yazwas
  • 101
  • 1
  • 9

3 Answers3

4

Do I need to wrap them all in another object and give each one a type?

  1. It is probably a better design to create a class that will aggregate all object instances. This will prevent bugs and result in much more readable code.

  2. If you just want to exchange plain java objects between a client and server you are better off using something like Remote method invocation (examples included in article).

How to extend this code to be able to send different types of objects from server?

If you insist on learning sockets you can just send and receive the object instances one after the other.

You can also send arrays of objects.

Client example:

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 6060);

        try {
            ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
            Student student = (Student)objectInput.readObject();

            System.out.println("Received student (" + student + ")");

            objectInput = new ObjectInputStream(socket.getInputStream());
            Teacher teacher  = (Teacher) objectInput.readObject();

            System.out.println("Received teacher (" + teacher + ")");

            //do something with std
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  finally {
            socket.close();
        }
    }
}

Server example:

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket myServerSocket = new ServerSocket(6060);
        System.out.println("Up and running");
        Socket skt = myServerSocket.accept();   
        try {
            Student student = new Student();
            ObjectOutputStream objectOutput = new ObjectOutputStream(skt.getOutputStream());
            objectOutput.writeObject(student);
            System.out.println("Sent student");

            Teacher teacher = new Teacher();
            objectOutput = new ObjectOutputStream(skt.getOutputStream());
            objectOutput.writeObject(teacher);
            System.out.println("Sent teacher");
        } 
        catch (IOException e) {
            e.printStackTrace();
        } finally {
            myServerSocket.close();
        }

        System.out.println("Shutting down");
    }
}

But this approach is hard to understand and bug prone, because if you don't get the order right on both the Client and Server then this code won't work.

Benjamin Albert
  • 738
  • 1
  • 7
  • 19
2

As I understand the question, you want to know how to detect what type of object is being sent to you I suspect instanceof and similar methods will do the trick.

You can also use an envelope to wrap the object in. This does pretty much the same but might allow you the opportunity to have error flags, routing information, urgency flags in there.

public static class Envelope implements Serializable {
    private final Object contents;
    private final String type;

    public Envelope(final Object contents, String type) {
        this.contents = contents;
        this.type = type;
    }

    public <T> T getContents(Class<T> clazz) {
        return (T) contents;
    }

    public String getType() {
        return type;
    }
}

public static void main(String[] argv) {

    Envelope stringEnvelope = new Envelope("abcd", "String");

    PipedInputStream reader = new PipedInputStream();
    PipedOutputStream writer = new PipedOutputStream();

    try {
        reader.connect(writer);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(writer);
        ObjectInputStream objectInputStream = new ObjectInputStream(reader);

        objectOutputStream.writeObject(stringEnvelope);

        Envelope envelope = (Envelope) objectInputStream.readObject();
        String type = envelope.getType();
        if (type.equals("String")) {
            String result = envelope.getContents(String.class);
            System.out.println(result);
        }
    } catch (ClassNotFoundException c) {

    } catch (IOException e) {

    }

}
Joeblade
  • 1,735
  • 14
  • 22
0

You could wrap your Object in a new Class:

public class ObjectMessage{
    public objecttype;
    public Object payload;
    public ObjectMessage(int objt, Object pay){
        objecttype=objt;
        payload=pay;
    }
}

Of course, you need to change the client, too:

Socket socket = new Socket(ip, port);
try {
    ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
    try {
        Object object = objectInput.readObject();
        ObjectMessage msg = (ObjectMessage) object;
        if(msg.objecttype == 0){
            Student std = (Student) msg.payload;
            //do something with std
        }else if(msg.objecttype == 1){
            //do something with Teacher, Book or whatever
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }      

And the server now does:

Student a = new Student(); //or Teacher, Book etc.
ObjectMessage message = new ObjectMessage(0,a); //use other numbers for other objects
ServerSocket myServerSocket = new ServerSocket(port);
Socket skt = myServerSocket.accept();   
try 
{
    ObjectOutputStream objectOutput = new ObjectOutputStream(skt.getOutputStream());
    objectOutput.writeObject(message);                
} 
catch (IOException e) 
{
    e.printStackTrace();
} 

(you might want to take a look at serialization too: What is object serialization?)

Community
  • 1
  • 1
ApolloLV
  • 152
  • 8