2011-04-14 70 views
21

我想創建一個新的ObjectInputStream使用從Socket中檢索的InputStream。這是我的代碼:Java創建一個新的ObjectInputStream塊

這是我的MessageGetterSender類的構造函數。該方案沒有得到到檢查點4

public MessageGetterSender(Socket socket) { 

    System.out.println("MessageGetterSender: Checkpoint 1"); 

    this.socket = socket; 

    // Get input and output streams 
    try { 
     System.out.println("MessageGetterSender: Checkpoint 2"); 

     InputStream is = socket.getInputStream(); 

     System.out.println("MessageGetterSender: Checkpoint 3"); 

     this.in = new ObjectInputStream(is); 

     System.out.println("MessageGetterSender: Checkpoint 4"); 

    } catch (IOException ioe) { 
     System.out.println("Could not get ObjectInputStream on socket: " + socket.getLocalPort()); 
    } 

    try { 
     this.out = new ObjectOutputStream(socket.getOutputStream()); 
    } catch (IOException ioe) { 
     System.out.println("Could not get ObjectOutputStream on socket: " + socket.getLocalPort()); 
    } 

    System.out.println("MessageGetterSender: Checkpoint 5"); 
} 

我從我連接到服務器,以獲得插座一個類實例化一個新的MessageGetterSender對象。這是相關的代碼。它是爲InstantMessageClass構造函數,來實例化MessageGetterSender對象的類:

public InstantMessageClient(String username) { 

try { 
    socket = new Socket("localhost", 5555); 
} catch (IOException ioe) { 
    System.out.println("Error: Could not connect to socket on port: " + serverPort); 
} 

messageGetterSender = new MessageGetterSender(socket); 

... 

由於代碼不執行到檢查點4,但它確實得到檢查點3,我敢肯定的ObjectInputStream的實例是罪魁禍首。我不明白爲什麼。有任何想法嗎?謝謝您的幫助。

回答

41

當你構造一個ObjectInputStream時,在構造函數中,類嘗試讀取連接另一端寫入的相關聯的ObjectOutputStream的標題。只有在讀取頭文件之後纔會返回。所以如果你看到構造函數'掛起',那是因爲套接字的另一端或者沒有使用ObjectOutputStream,或者沒有刷新數據。

42

爲了擴大FatGuy對其他Google員工的答案,解決這個「雞和雞蛋問題」的辦法是讓每一邊先打開輸出流,刷新輸出流,然後打開輸入流。

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); 
out.flush(); 
ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 
+5

這確實是一個合適的解決方案。你把它描述成一個「雞和雞蛋」問題,並將它釘在頭上。 – Timmos 2013-06-30 19:20:27

+0

我會說''out.flush()'是沒有必要的(除非你使用一些緩衝流作爲基礎流),因爲'ObjectOutputStream'使用的'BlockDataOutputStream'在它啓用塊數據模式之前寫入流標題。 – Dominik 2017-03-07 12:53:45

2

您還可以延遲ObjectInputStream的初始化,直到數據在基礎流中可用。

無論流的初始化順序如何,此方法都可以工作,如果通道的一端位於無法更改的庫代碼中,則此方法尤其有用。

+1

我可以問一下如何去做這件事? – Jack 2014-02-24 00:21:23