我面临着通过TCP套接字发送和接收序列化对象的问题。实际上,我可以在服务器线程和客户端线程之间正确地接收/发送对象。但是,问题是如果更改了接收/发送对象的属性值,则等待线程无法实现此更改。请考虑此代码示例;
public class ClientThread extends javax.swing.JFrame implements Runnable {
ClientObject mainClient; // Initiliazed after sockets connect to server successfully
.
.
.
String addNewBuddy = JOptionPane.showInputDialog(this, "Enter the Username of the person who you want to add...");
mainClient.setBuddyRequest(true);
mainClient.setBuddyRequestAccount(addNewBuddy);
send.writeObject(mainClient); // write into an ObjectOutputStream
send.flush(); // flush it
System.out.println("mainClient.setBuddyRequest : " + mainClient.isBuddyRequest() + " setBuddyRequestAccount : " + mainClient.getBuddyRequestAccount()); // Check if values changed properly
ClientObject tempClientObject; // temporary an instance of ClientObject
while(( tempClientObject = (ClientObject) receive.readObject()) != null){
if( !tempClientObject.isBuddyRequest() ){
JOptionPane.showMessageDialog(this, "Buddy Request Information", "Requested buddy doesnt exist!!!", JOptionPane.ERROR_MESSAGE);
break;
}
else{
JOptionPane.showMessageDialog(this, "Buddy Request Information", "Requested buddy added into your buddy list succesfully", JOptionPane.INFORMATION_MESSAGE);
labelSetText = tempClientObject.getNickName();
onlineStatus = tempClientObject.isIsOnline();
model.addElement(createPanel());
}
}
.
.
.
}
所以在我改变mainClient
的一些属性后,我将它发送到服务器。这是服务器线程等待对象给出一些反应的部分。此外,当客户端发送第二个对象(使计数器大于0)时,服务器线程可以无错误地读取它,但我发现即使客户端将修改后的对象作为第二个消息发送到服务器,第一个和第二个对象的属性之间也没有差异!
while( ( clientO = (ClientObject) receive.readObject()) != null ){
counterMessage++;
if( counterMessage==1) { //
checkAccountIfExist(toWrite,file.exists(),toModify,clientO); // Check is connected account exist in database of server
} // end of if (counter==1)
else{ // Second time when server waits
// prints counter=2 but clientO.isBuddyRequest printed as 'false'
//instead of 'true' so this makes if statement unreachable!
System.out.println("Counter = " + counterMessage + " BUDDYREQUEST : " + clientO.isBuddyRequest() + " USERNAME : " + clientO.getUserName());
if(clientO.isBuddyRequest()){
System.out.println("Entered");
checkBuddyAvalaible(clientO);
}
}
}
最后是我的序列化ClientObject的代码
public class ClientObject implements Serializable {
private static final long serialVersionUID = 8662836292460365873L;
private String userName;
private String password;
private String nickName;
private String message;
private boolean checkAcc;
private LinkedList<ClientObject> buddyList;
private boolean isOnline;
private boolean buddyRequest;
private String buddyRequestAccount;
public ClientObject(String userName, String password){
this.userName = userName;
this.password = password;
this.checkAcc = false;
this.buddyList = new LinkedList<ClientObject>();
this.isOnline = false;
this.buddyRequest = false;
this.buddyRequestAccount = null;
}
...methods of getters and setters
}
我希望我已经明确了这个问题,我会对每一个答案都表示赞赏,不管怎样,谢谢。
答案 0 :(得分:3)
您需要做的就是调用ObjectOutputStream.reset(),或者使用writeUnshared()。
答案 1 :(得分:1)
我猜你正在写发送代码:
.....
mainClient = new ClientObject(userName, password);
String clientNickName = JOptionPane.showInputDialog(this, "Enter your NickName");
mainClient.setNickName(clientNickName);
send.writeObject(mainClient);
send.flush();
......
在一个循环中。如果是这样,你应该阅读关于java序列化的这个事实:
在执行对象的序列化时,Java形成数据结构 类似于对象图,以确定需要哪些对象 序列化。它从主要对象开始序列化,并且 递归遍历从主对象可到达的所有对象。 对于它遇到的每个对象,需要序列化,它 关联标记该对象的标识符 序列化到给定的ObjectOutputStream实例。所以当Java 遇到已标记为序列化的同一对象 到ObjectOutputStream,它不会再次序列化对象, 而是序列化同一对象的句柄。这就是Java 避免必须重新序列化已经序列化的对象。
编辑
根据 EJP的评论,我更新了帖子,向OP提供了正确的信息。
第一次通过ClientObject
向OutputStream
发送ObjectOutputStream
对象后,下次发送ClientObject
的更改对象时,java会检查此类对象是否为已被序列化。由于它已经被序列化,所以java不会序列化再次创建的新object
。这就是为什么你在另一边得到同样的对象。
对此问题的回忆是,每次您要发送ClientObject
的已更改对象时,请重置ObjectOutputStream
,如:
send.reset();
然后将更改的对象发送到另一端。