Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 服务器线程无法看到序列化对象的已更改字段_Java_Sockets_Serialization_Objectoutputstream_Objectinputstream - Fatal编程技术网

Java 服务器线程无法看到序列化对象的已更改字段

Java 服务器线程无法看到序列化对象的已更改字段,java,sockets,serialization,objectoutputstream,objectinputstream,Java,Sockets,Serialization,Objectoutputstream,Objectinputstream,我面临通过TCP套接字发送和接收序列化对象的问题。实际上,我可以在服务器线程和客户端线程之间正确地接收/发送对象。但是,问题是,如果更改了接收/发送对象的属性值,则等待的线程无法实现此更改。考虑这个代码示例; public class ClientThread extends javax.swing.JFrame implements Runnable { ClientObject mainClient; // Initiliazed after sockets connect to serv

我面临通过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);
                     }

                 }

        }
最后是我的SerializeLible 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
}
公共类ClientObject实现可序列化{
私有静态最终长serialVersionUID=8662836292460365873L;
私有字符串用户名;
私有字符串密码;
私有字符串昵称;
私有字符串消息;
私有布尔校验;
私人关系主义者;
私有布尔等值线;
私有布尔buddyRequest;
私有字符串buddyRequestAccount;
公共ClientObject(字符串用户名、字符串密码){
this.userName=用户名;
this.password=密码;
this.checkAcc=false;
this.buddyList=新建LinkedList();
this.isOnline=false;
this.buddyRequest=false;
this.buddyRequestAccount=null;
}
…getter和setter的方法
}

我希望我已经清楚地了解了这个问题,我将感谢您的每一个回答,无论如何,谢谢。

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

.....
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的评论,我已经更新了帖子,为运营部提供了正确的信息。
第一次通过
ObjectOutputStream
ClientObject
的对象发送到
OutputStream
后,下次发送
ClientObject
的更改对象时,java将检查此类型的对象是否已被序列化。因为它已经被序列化了,所以java不会再次序列化新创建的
对象。这就是为什么你们在另一边得到同样的物体
解决此问题的方法是,每次要发送
ClientObject
的已更改对象时,请重置
ObjectOutputStream
如下所示:

send.reset();  

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

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

.....
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的评论,我已经更新了帖子,为运营部提供了正确的信息。
第一次通过
ObjectOutputStream
ClientObject
的对象发送到
OutputStream
后,下次发送
ClientObject
的更改对象时,java将检查此类型的对象是否已被序列化。因为它已经被序列化了,所以java不会再次序列化新创建的
对象。这就是为什么你们在另一边得到同样的物体
解决此问题的方法是,每次要发送
ClientObject
的已更改对象时,请重置
ObjectOutputStream
如下所示:

send.reset();  

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

只需调用ObjectOutputStream.reset(),或使用writeUnshared()。

只需调用ObjectOutputStream.reset(),或使用writeUnshared()即可.

显示序列化和发送
ClientObject对象的代码这里是我没有放完整代码的链接,因为它有点复杂
mainClient
是ClientObject的类型,在此代码示例中,它是第一次初始化并发送到服务器。第二次发送对象的代码是什么?链接,用于在将主对象发送到服务器之前设置主对象的两个字段。如您所见,
setBuddyRequest
setBuddyRequestAccount
在发送之前已更改。服务器线程等待接收对象的while语句的链接