2013-03-10 81 views
-5

我有一個Java程序從TCP源讀取數據的工作都很好,除非我的程序(它充當數據源的客戶端)比那時更快源可以響應BufferedReader.ready()拋出一個異常,它會關閉我的TCP連接,因爲它應該如此。是否有任何首選的方法/方法可以讓BufferedReader等待新的輸入,因爲我的源有時可能會有輕微的延遲。緩衝套接字讀取器不等待遠程連接的數據

這是我講的一部分:你不應該使用ndataServerReader.ready()

public aDataServer(String host, int port, StreamConnection aConnection) throws UnknownHostException, IOException { 
      this.aConnection = aConnection; 
      ndataServerSocket = new Socket(Inet4Address.getByName(host),port); 
      ndataServerReader = new BufferedReader(new InputStreamReader(ndataServerSocket.getInputStream())); 
     } 


public void run() { 
      try { 
       RemoteDevice dev = RemoteDevice.getRemoteDevice(aConnection); 
       OutputStream outputStream = aConnection.openOutputStream(); 
       OutputStreamWriter osw = new OutputStreamWriter(outputStream); 
       do { 
        try { 
         String ndata = ndataServerReader.readLine(); 


          osw.write(ndata+"\n"); 
          osw.flush(); 
          LOG.log(Level.INFO,"Sent"); 


        } catch(IOException io) { 
         LOG.log(Level.SEVERE, "Client device({0}) disconnected: \n{1}", new Object[]{dev.getFriendlyName(true), io.getMessage()}); 
         break; 
        } 
       }while(ndataServerReader.ready()); 
      } catch (IOException ioe) { 
       LOG.severe(ioe.getMessage()); 
      } finally { 
       try { 
        if (ndataServerSocket != null) { 
           ndataServerSocket.close(); 
        } 
        if (ndataServerReader 
          != null) { 
           ndataServerReader.close(); 
        } 
       } catch (IOException ex) { 
        LOG.log(Level.SEVERE, ex.getMessage()); 
       } 
      } 
+1

什麼是拋出異常?你能否包含你如何構建和讀取BufferedReader的代碼片段? – dimo414 2013-03-10 19:43:19

+0

用一些代碼更新了我的問題 – user1945235 2013-03-10 19:53:04

+0

您是否也可以發佈異常輸出? – dimo414 2013-03-10 19:58:38

回答

0

。你的do/while循環(幾乎肯定只是一個while循環)似乎假設ndataServerReader.ready()表示有更多的數據要讀取,這不是它的用途。

Javadoc for Reader描述ready()方法爲:

判斷此流是否已準備好被讀取。

返回:如果下一個read()保證不會阻塞輸入,則返回true,否則返回false 。請注意,返回false並不能保證讀取的下一個 將被阻止。

在其他情況下,如果讀者在嘗試從中讀取數據時將返回之前等待更多數據,則Reader.ready()將返回false。這是而不是意味着讀者已完成,事實上你應該期望這種方法經常在使用網絡流時返回false,因爲它可能很容易出現延遲。

您的代碼當前有可能讀取一行(在do區塊中),然後檢查讀取器是否已準備就緒(在while中),這可能不是,然後成功退出。沒有任何例外 - 如果是的話,你會看到SEVERE級別的日誌消息。

而不是使用ready()的,採取的說,它返回的readLine()的記錄的行爲的優勢:

包含行的內容,不包括任何 行終止字符的字符串,或NULL,如果該流的末尾已經達到

換句話說,簡單地做:

String ndata = reader.readLine(); 
while (ndata != null) { 
    osw.write(ndata+"\n"); 
    osw.flush(); 
    LOG.log(Level.INFO,"Sent"); 

    ndata reader.readLine(); 
} 

足以讀取整個輸入流。

參考閱讀:What's the difference between (reader.ready()) and using a for loop to read through a file?

+0

謝謝,現在更加合理。如果我正確理解這一點,這也不會在等待時造成巨大的CPU使用量。 – user1945235 2013-03-10 21:47:40

+0

不應該,線程只是等待(在一個循環中有效地執行'Thread.sleep()',儘管實際的實現是本地OS代碼),直到它從源獲得足夠的數據,或者它比允許的超時,你可以在Socket對象中設置,在這種情況下會拋出一個異常,表示沒有足夠的數據返回。 – dimo414 2013-03-10 21:59:24