I have several classes running at the same time which get input from a server. Both have the sockets set up.
The problem is that, even though I transfer the same data between the classes, when the data arrives, it is not the same.
Here is the sending method:
private boolean transferBroadcastData() {
boolean success = false;
开发者_如何学Gotry {
Vector<Client> clientsList =
onlineList.getClientsList();
for (Client client : clientsList) {
ObjectOutputStream objectOutputStream =
client.getObjectOutputStream();
objectOutputStream.writeObject(clientsList);
objectOutputStream.flush();
}
success = true;
} catch (Exception ioException) {
ioException.printStackTrace();
}
return success;
}
And here is the receiving-method:
while (true) {
try {
Object object = objectInputStream.readObject();
if (object instanceof Vector<?>) {
String x = "I got it:\n";
Vector<Client> clients = (Vector<Client>) object;
for(Client c : clients) {
x += "\n" + c;
}
JOptionPane.showMessageDialog(ClientManager.this, x);
usersPanel.addClientsToList((Vector<Client>) object);
}
else if (object instanceof Message)
messagePanel.appendText((Message) object);
} catch (ClassNotFoundException classNotFoundException) {
statusPanel.updateStatus("Error reading from socket");
}
}
When I receive the Vector on all my clients, the elements in it are different. It is not the content of the Vector I tried to transfer.
What am I missing?
The problem is likely with your use of Serialization / ObjectOutputStream. When an object is serialized ObjectOutputStream keeps internal records to "optimize" the serialization process, so that if you serialize the same object twice it simply repeats the ID and assumes the object hasnt changed. For example if you run the code:
ObjectOutputStream oos = new ObjectOutputStream();
MyObject[] arr = new MyObject[]{myObject};
oos.write(myObject);
oos.write(arr);
the output might look like (note not actual format just an example):
[[myObject;id=357;foo=bar;baz=36;]]
[[MyObject[];id=358;data={id=357}]]
Note that the array will not serialize the object again, but rather just an id to the already serialized version. Taking it one step further if you have the code:
ObjectOutputStream oos = new ObjectOutputStream();
oos.write(myObject);
myObject.setBaz(99999);
oos.write(myObject);
You'll end up with:
[[myObject;id=357;foo=bar;baz=36;]]
{id=357}
Note that even though the object changed only the internal id is serialized. The trick is when you are writing objects you need to clear the internal state of the ObjectOutputStream, which can be accomplished with reset(). From the javadocs:
Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream.
So if you take the previous example and add reset:
ObjectOutputStream oos = new ObjectOutputStream();
oos.write(myObject);
myObject.setBaz(99999);
oos.reset();
oos.write(myObject);
You should get as output the expected behaviour of:
[[myObject;id=357;foo=bar;baz=36;]]
[[myObject;id=358;foo=bar;baz=99999;]]
One things to be careful of is to note that the second serialization will now be considered a different object than the original serialization. Depending on how you are transferring the data and the internal relationship you must be careful not to reset the stream too early if objects share references with one another and you want those relationships to be maintained.
精彩评论