我有一个典型的多线程服务器和一个客户端,它通过套接字与服务器连接并进行一些操作。
客户端部分:
try {
mySocket=new Socket("localhost", 1234);
ObjectOutputStream oos= new ObjectOutputStream(mySocket.getOutputStream());
ObjectInputStream ois= new ObjectInputStream(mySocket.getInputStream());
try{
while(true){
//Here user is asked for input the protocol string
if("one message".equals(protocol))
{
oos.writeObject(protocol);
oos.flush();
mylist=(ArrayList<MyClass>)ois.readObject();
System.out.println(mylist);
}
if("two message".equals(protocol))
{
//tell server to change few things on the list
}
}//end while
} //end inner try
catch (IOException | ClassNotFoundException ex)
{
// ex.printStackTrace();
}
ois.close();
oos.close();
mySocket.close();
}//end outer try
catch (IOException e)
{
//message
}
服务器端:
public void run() {
try{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
String protocol;
try{
while(true)
{
protocol= (String)ois.readObject();
if ("one message".equals(protocol))
{
oos.writeObject(list);
oos.flush();
System.out.println(list);
}
if ("two message".equals(protocol))
{
//change objects in the list
}
} //end while true
} //end try
catch (IOException | ClassNotFoundException ex)
{
// ex.printStackTrace();
}
ois.close();
oos.close();
socket.close();
}
catch (Exception ex)
{
//ex.printStackTrace();
}
}
有问题的部分在这里:
if ("one message".equals(protocol))
{
oos.writeObject(list); //sends the wrong (?)
oos.flush();
System.out.println(list); //prints the correct
}
服务器从侧面看,似乎每次用户更改时都会打印正确的列表。但是,无论客户进行多少更改,客户都会收到并打印第一个列表。如果另一个线程出现并要求列表,它将采用最新列表,如果该线程或其他线程进行更多更改,服务器仍将每次从其侧面打印正确的列表,但客户端将始终返回错误的列表,这是该客户端线程进入时存在的列表。
答案 0 :(得分:1)
ObjectOutputStream,如果您要求它发送已发送的对象,只需发送对先前发送的对象的引用。这允许发送对象的复杂图形,具有双向引用或对象之间的循环。
如果您希望流忘记已发送的内容,则需要调用reset()
方法。
答案 1 :(得分:0)
您是序列化流中对象缓存的受害者。第一次编写对象时,正在为该参考地址创建缓存版本。然后每次你写它(即使你改变内容)它不再写它,因为它说“我已经看起来像这个地址的对象”。
解决此问题的最佳方法是将套接字流保留在while循环之外,但将ObjectOutput和ObjectInput流放在while循环中。这应该可以解决您的问题。通常,其中一组是针对一个稳定对象图设计的。