Leo*_*rra 1 java objectoutputstream objectinputstream
我正在开发一个Client-Server项目(你可以称之为"广播聊天"),但我遇到了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);
}
}
Run Code Online (Sandbox Code Playgroud)
客户:
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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户端应该发送我写入服务器的内容,然后将相同的消息发送给每个连接的客户端.当我写东西时,这就是服务器端和客户端发生的事情:
服务器日志:
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: []
Run Code Online (Sandbox Code Playgroud)
客户日志:
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 : []
Run Code Online (Sandbox Code Playgroud)
如果我用"lstr = new LinkedList();"替换sendMsg()中的lstr.clear(); 它应该工作,但我不知道为什么:(
客户端日志(修复后):
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 : []
Run Code Online (Sandbox Code Playgroud)
如何解释这种行为?
序列化协议保留了对象标识.
如果您重复编写同一个对象,它将不再使用其内容进行序列化,该流将只包含一个反向引用,以指示您再次编写同一个对象.
因此,流只会在您第一次发送时包含列表的状态,即为空.
当您稍后将内容添加到列表并再次写入列表时,将无法获取.该流只包含一个标签,上面写着"之前的列表".
当您从更改list.clear()为创建一个全新的列表实例时,您可以解决此问题:现在,在编写时,每个列表都会使用其数据写入流.
| 归档时间: |
|
| 查看次数: |
140 次 |
| 最近记录: |