2017-01-31 11 views
0

私はClient-Serverプロジェクト( "Broadcast Chat"と呼ぶことができます)で作業していますが、ObjectInputStreamに問題があります。ObjectInputStreamは常に空のListを取得します

:それは常に私に空のリストを取得し、これは盗聴コード(サーバーのSENDMSG()関数を確認してください)です 私は解決策を見つけたが、それが動作する理由がわからない...

SERVER:

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

    } 



} 

CLIENT:

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 : [] 

私はlstrを交換する場合は、私が何かを書くとき これは、サーバ側とクライアント側に何が起こるかです。 "lstr = new LinkedList();を指定してsendMsg()で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 : [] 

+1

lstr.clear()を呼び出すと、currectオブジェクトのコンテンツが削除されます。 lstr = new ...を呼び出すと、lstrは別のオブジェクトを指し示しますが、現在のオブジェクトの内容は削除されません – Egl

答えて

4

直列化プロトコルは、オブジェクトのアイデンティティを維持します。

同じオブジェクトを繰り返し書き込むと、そのオブジェクトの内容が再びシリアライズされることはありません。ストリームには、同じオブジェクトを別の時間書き込んだことを示す逆参照が含まれます。

その結果、ストリームには最初に送信したときの状態、つまり空の状態のみが含まれます。

後でリストに項目を追加してリストを書き直すと、それは取得されません。ストリームには、「その前からのリスト」というラベルが含まれます。

list.clear()から完全に新しいリストインスタンスに変更すると、これを修正しました。今、すべてのリストは、書き込み時にデータとともにストリームに書き込まれます。

関連する問題