如何在 Java 的套接字中使用 readObject() 两次? [英] How to use readObject() twice in socket of Java?

查看:58
本文介绍了如何在 Java 的套接字中使用 readObject() 两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的客户端代码:

公共客户端(){MessageClass messageobject=new MessageClass("登录");messageobject.SetLoginUserInfo("18580409","12345","magicgiant");尝试{客户端=新套接字(本地主机",1234);System.out.println("已连接!");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);}捕获(例外 e){System.out.println(e);}}

这是我的服务器:

public void run(){尝试{is=new ObjectInputStream(client.getInputStream());}捕获(异常前){System.out.println(ex);}而(真){尝试{MessageClass messageobject = (MessageClass)is.readObject();System.out.println(messageobject.GetLoginId()+messageobject.GetLoginPassword());idSocketItem = new IdSocket(messageobject.GetLoginId(),client,messageobject);s.idSocketList.addElement(idSocketItem);}捕获(异常前){System.out.println(ex);}}}

服务器中的 System.out 应该是

185804091234512213121312

但真正的结果是

18580409123451858040912345

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

解决方案

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

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 命名约定,并将所有字段设为私有以鼓励封装.

I used the ObjectStream in Socket to transport the class. The client transports two different data in same class, but the server gets the second data that is same as the first data. It is strange!

Here is my code of client:

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);
    }
}

Here is my server:

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);
     }

   }    
}

The System.out in server should be

1858040912345
12213121312

But the real result is

1858040912345
1858040912345

I have tried to cancel the flush(), but it does not work. Where is the problem?

解决方案

The problem is that you're writing the same reference twice:

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

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

ObjectOutputStream caches the fact that you've written that reference, and just emits a token to refer to the previous value. Three options to consider:

  • (Preferred, IMO): Create a new object instead of modifying the existing one
  • Call writeUnshared() instead of writeObject():

    This method is identical to writeObject, except that it always writes the given object as a new, unique object in the stream (as opposed to a back-reference pointing to a previously serialized instance).

  • Call reset() on the stream after writing the first object:

    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. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.

I prefer the first version as logically you've got two different messages - so they should be two different objects.

Additionally, I'd strongly encourage you to start following Java naming conventions, and make all your fields private to encourage encapsulation.

这篇关于如何在 Java 的套接字中使用 readObject() 两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆