1

我面临一个关于通过 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
}

我希望我已经清楚这个问题,我会感谢每一个答案,无论如何,谢谢。

4

2 回答 2

3

您需要做的就是调用 ObjectOutputStream.reset(),或使用 writeUnshared()。

于 2013-03-27T23:06:19.440 回答
1

我猜您正在编写发送代码:

.....
mainClient = new ClientObject(userName, password);
String clientNickName = JOptionPane.showInputDialog(this, "Enter your NickName");
mainClient.setNickName(clientNickName);
send.writeObject(mainClient);
send.flush();
......

在一个循环中。如果是这样,您应该阅读有关 java 序列化的事实:

在执行对象的序列化时,Java 会形成一个类似于 Object Graph 的数据结构来确定哪些对象需要被序列化。它从主对象开始进行序列化,递归地遍历所有从主对象可达的对象。对于它遇到的每个需要序列化的对象,它将一个标识符关联到一个给定的 ObjectOutputStream 实例,该标识符将该对象标记为已序列化。所以当Java遇到已经被标记为序列化到ObjectOutputStream的同一个对象时,它不会再序列化这个对象,而是序列化同一个对象的句柄。这就是 Java 避免重新序列化已经序列化的对象的方式。


编辑
根据EJP 的评论,我更新了帖子以向 OP 提供正确的信息。
在第一次向 via 发送对象后ClientObjectOutputStream下次ObjectOutputStream发送更改后的ClientObjectjava 对象时会检查此类型的对象是否已被序列化。由于它已经被序列化了,所以java不会object再次序列化新创建的。这就是为什么你在另一边得到相同的对象。
解决这个问题的方法是每次你想发送ClientObject重置的更改对象时ObjectOutputStream

send.reset();  

然后将更改后的对象发送到另一端。

于 2013-03-27T19:49:36.273 回答