我正在开发一个Client-Server项目(您可以调用它" Broadcast Chat")但是我遇到了ObjectInputStream的问题。 它总是检索我一个空列表,我找到了解决方案,但我不知道它为什么有效...
这是有问题的代码(检查服务器的sendMsg()函数):
服务器
public class CoreServer implements Runnable {
private Socket sock;
private ServerConnect sc;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private boolean running=true;
private List<String> lstr;
public CoreServer(Socket sock, ServerConnect sc) {
this.sock=sock;
this.sc=sc;
}
@Override
public void run() {
lstr=new LinkedList<String>();
try {
oos= new ObjectOutputStream(sock.getOutputStream());
ois=new ObjectInputStream(sock.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
while (running){
Object o=null;
try {
o= ois.readObject();
} catch (ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
sc.remove(this);
stop();
}
if (Integer.class.isInstance(o)){
try {
int num= (Integer) o;
if(num==0){
sendMsg();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (String.class.isInstance(o)){
System.out.println("String Received");
String ss= (String) o;
sc.readyToSend(ss);
}
}
}
public void sendMsg() throws IOException{
try {
System.out.println("I'm going to send: "+lstr);
oos.writeObject((Object)lstr);
oos.flush();
lstr.clear();
// If I replace lstr.clear() with "lstr=new LinkedList();" it works as it should.
} catch (IOException e) {
e.printStackTrace();
}
}
public void addMsg(String text){
System.out.println("I will add -"+text+"- to the list");
lstr.add(text);
}
}
客户端:
public class ClientConnect implements Runnable {
private Socket sock;
private boolean running=true;
private ObjectInputStream ois;
private ObjectOutputStream oos;
private boolean first=true;
private Object o;
private ClientFrame cf;
public ClientConnect(Socket sock, ClientFrame cf){
this.sock=sock;
this.cf=cf;
}
@Override
public void run() {
if (first){
try {
oos= new ObjectOutputStream(sock.getOutputStream());
ois= new ObjectInputStream(sock.getInputStream());
first=false;
} catch (IOException e) {
e.printStackTrace();
}
}
while (running){
try {
oos.writeObject(new Integer(0));
oos.flush();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Connection error");
this.stop();
System.exit(1);
}
try {
o=ois.readObject();
System.out.println("I received o : "+(List)o);
} catch (ClassNotFoundException | IOException e) {
JOptionPane.showMessageDialog(null, "Server offline");
System.exit(1);
}
if(List.class.isInstance(o)){
List<String> l=null;
l=(List<String>) o;
Iterator<String> it= l.iterator();
while (it.hasNext()){
String s=it.next();
System.out.println("Adding:"+s);
cf.history.append(s+ "\n"); //this function will show the received content on a JTextArea
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void send(String text){
if (!text.equals("")){
try {
oos.writeObject(text);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端应该发送我写入服务器的内容,然后将相同的消息发送给每个连接的客户端。 当我写东西时,这就是服务器端和客户端发生的事情:
服务器日志:
Waiting client
Found one client
Waiting client //The Server is multithreaded and is waiting for another client to connect
Waiting client
I'm going to send: []
I'm going to send: []
I'm going to send: []
String Received
I will add -Hello- to the list
I'm going to send: [Hello]
I'm going to send: []
I'm going to send: []
I'm going to send: []
String Received
I will add -Stackoverflow- to the list
I'm going to send: [Stackoverflow]
I'm going to send: []
I'm going to send: []
I'm going to send: []
I'm going to send: []
客户日志:
I received o : []
I received o : []
I received o : []
You wrote: Hello
I received o : [] <-- it can't read the list that the server sent to me.
I received o : []
I received o : []
I received o : []
You wrote: Stackoverflow
I received o : [] <-- it can't read the list that the server sent to me.
I received o : []
I received o : []
I received o : []
I received o : []
如果我用&#34替换sendMsg()中的lstr.clear(); lstr = new LinkedList();&#34;它应该工作,但我不知道为什么:(
客户端日志(修复后):
I received o : []
I received o : []
I received o : []
You wrote: Hello
I received o : [Hello]
Adding:Hello
I received o : []
I received o : []
I received o : []
You wrote: Stackoverflow
I received o : [StackOverflow]
Adding:StackOverflow
I received o : []
I received o : []
I received o : []
I received o : []
如何解释这种行为?
答案 0 :(得分:5)
序列化协议保留了对象标识。
如果您重复编写同一个对象,它将不会再次使用其内容进行序列化,该流将只包含一个反向引用,以指示您再次编写相同的对象。
因此,流只会在您第一次发送时包含列表的状态,即为空。
当您稍后将内容添加到列表并再次写入列表时,将无法获取该列表。该流只会包含一个标签,上面写着“再次列出该列表”。
当您从list.clear()
更改为创建一个全新的列表实例时,您可以解决此问题:现在,在编写本文时,每个列表都会使用其数据写入流。