Send and receive an object via DatagramChannels

199 views Asked by At

I have a problem with ByteArrayInputStream + ObjectInputStream (and corresponding output streams).

I want to write some (different) instances of the class Pair over an UDP channel, and I've managed to this way:

For writing (this.scores is a HashMap<String, Integer> and this.completed is an ArrayList<String> (assuming its size() is 2 in this example))

for(String userWhoCompleted : this.completed) {
    try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);) {

        oos.writeUnshared(new Pair<String, Integer>(userWhoCompleted, this.scores.get(userWhoCompleted)));
        oos.flush();
        this.resultChannel.write(ByteBuffer.wrap(baos.toByteArray()));
    } catch(IOException e) { e.printStackTrace(); }
}

For reading (buf is a ByteBuffer)

while(scoresReceived != 2) { // 2 is temporary
    buf.clear();
    try {
        this.multicastChannel.receive(buf);
    } catch(IOException e) { e.printStackTrace(); }

    try(ByteArrayInputStream bais = new ByteArrayInputStream(buf.array(), 0, buf.position());
        ObjectInputStream ois = new ObjectInputStream(bais);) {

        Pair<String, Integer> result = (Pair<String, Integer>) ois.readUnshared();
        System.out.println(result);
    } catch(IOException | ClassNotFoundException e) { e.printStackTrace(); }

}

With this code I can read all the 2 objects written on the channel correctly.

But as you can see, I had to create a new instance of baos, oos, ois and bais on every new loop cycle. I tried to create those objects outside the loop, and then to do oos.writeUnshared(baos.toByteArray) + baos.reset() and readUnshared respectively on the server and client side but I got StreamCorruptedException: invalid stream header when reading. If I remove baos.reset() I read always the same object, that is the first written to the oos. What did I do wrong? Is this the only way to work around these problems?

PS: The class Pair is Serializable:

import java.io.Serializable;

public class Pair<F extends Serializable, S extends Serializable> implements Serializable {
    private static final long serialVersionUID = 1L;
    private F first;
    private S second;

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    public F getFirst() { return first; }

    public S getSecond() { return second; }

    public String toString() {
        return "First: " + this.first.toString() + " Second: " + this.second.toString(); 
    }
}
0

There are 0 answers