1

我使用 Socket 中的 ObjectStream 来传输类。客户端在同一类中传输两个不同的数据,但服务器获取的第二个数据与第一个数据相同。它很奇怪!

这是我的客户代码:

public Client()
{   
        MessageClass messageobject=new MessageClass("login");
        messageobject.SetLoginUserInfo("18580409","12345","magicgiant");

    try
    {
        client=new Socket("localhost",1234);
        System.out.println("Connected!");
        ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
        out.writeObject(messageobject);
        out.flush();
        System.out.println(1);

        messageobject.inquire=true;
        messageobject.SetLoginUserInfo("122131","21312","dfsd");
        out.writeObject(messageobject);
        out.flush();
        System.out.println(2);
    }
    catch(Exception e)
    {
        System.out.println(e);
    }
}

这是我的服务器:

public void run()
{  
  try
  {
     is=new ObjectInputStream(client.getInputStream());
  }
  catch (Exception ex)
  {
     System.out.println(ex);
  }

  while(true){

   try
   {  
      MessageClass messageobject = (MessageClass)is.readObject();   
      System.out.println(messageobject.GetLoginId()+messageobject.GetLoginPassword());
      idSocketItem = new IdSocket(messageobject.GetLoginId(),client,messageobject);
      s.idSocketList.addElement(idSocketItem);
    }
    catch (Exception ex)
    {
       System.out.println(ex);
     }

   }    
}

服务器中的 System.out 应该是

1858040912345
12213121312

但真正的结果是

1858040912345
1858040912345

我试图取消flush(),但它不起作用。问题出在哪里?

4

1 回答 1

2

问题是你写了两次相同的参考:

out.writeObject(messageobject);
out.flush();
System.out.println(1);

messageobject.inquire=true;
messageobject.SetLoginUserInfo("122131","21312","dfsd");
out.writeObject(messageobject);

ObjectOutputStream缓存您已编写该引用的事实,并仅发出一个标记来引用先前的值。需要考虑的三个选项:

  • (首选,IMO):创建一个新对象而不是修改现有对象
  • 调用writeUnshared()而不是writeObject()

    此方法与 writeObject 相同,不同之处在于它始终将给定对象作为流中新的唯一对象写入(与指向先前序列化实例的反向引用相反)。

  • reset()在写入第一个对象后调用流:

    重置将忽略已写入流的任何对象的状态。状态被重置为与新的 ObjectOutputStream 相同。流中的当前点被标记为重置,因此相应的 ObjectInputStream 将在同一点重置。之前写入流的对象不会被称为已经在流中。它们将再次写入流。

我更喜欢第一个版本,因为逻辑上你有两个不同的消息——所以它们应该是两个不同的对象。

此外,我强烈建议您开始遵循 Java 命名约定,并将所有字段设为私有以鼓励封装。

于 2013-06-09T12:06:24.380 回答