我使用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);
}
}
}
系统。Out in server应该是
1858040912345
12213121312
但是真正的结果是
1858040912345
1858040912345
我已经尝试取消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()
:Reset将忽略任何已经写入流的对象的状态。状态被重置为与新的ObjectOutputStream相同。流中的当前点被标记为重置,因此对应的ObjectInputStream将在同一点被重置。先前写入流的对象将不会被引用为已经存在于流中。它们将被再次写入流。
我更喜欢第一个版本,因为逻辑上你有两个不同的消息-所以它们应该是两个不同的对象。
此外,我强烈建议您开始遵循Java命名约定,并将所有字段设置为私有以鼓励封装。