2011-08-18 96 views
3

我有問題讓這個簡單的類工作。它基本上連接到IMAP服務器並讀取橫幅。但在閱讀所有字符後,它有點懸掛。在調試器中,我可以遍歷while循環,看到所有字符正在被讀取,並最終從循環中出來。但是最後的System.out.println語句永遠不會到達。如果從插座讀取

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.InputStreamReader; 
import java.net.Socket; 


public class TestClient 
{ 

    /** 

     @param args 

    */ 
    public static void main(String[] args) throws Exception 
    { 

     Socket socket = new Socket("imap.1and1.com", 143); 

     DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

     StringBuilder sb = new StringBuilder(); 
     char ch = (char) reader.read(); 
     while (ch != -1) { 
      sb.append(ch); 
      ch = (char) reader.read(); 

     } 

     System.out.println(sb.toString()); /// <--- never prints anything and program just hangs.. 
    } 

} 

回答

2

讀功能塊沒有數據讀取,只有當readStream被關閉或插座連接斷開了出來。你應該做的是創建一個協議,在完全讀取數據後斷開連接。即你應該來循環出

  • 或者通過某種方式斷開所有數據後,連接已 被讀取(對於您必須確定所有數據已經​​讀取)

  • 或出去的循環自己,如果你看過一些事先約定 串「消息的結束」 ..

一兩件事,因爲閱讀()塊,等待更多的數據,建議你應該在後臺線程讀取..

+0

在線路協議類型的服務器應用程序(例如:POP/IMAP)沒有預定義字符來指示特定的命令結果的末尾。在這種情況下做什麼?順便說一句,在我上面的示例中的readline。但我期待多於單行,並將readLine放入循環中也會阻止。 – Mir3

+0

然後您正在使用BufferedReader..check如果有任何選項可以告訴讀取功能在沒有數據要讀取時不會阻止。 – Krishnabhadra

0

好吧,這是我做了什麼來解決我的特殊問題。請注意,使用ready()或available()方法並不總是可靠的。特別是如果服務器需要發送數據,暫停然後發送更多的數據。在我的情況下,它的工作原理是,我不希望服務器在響應中停止並重新啓動。

該代碼顯然未針對實際使用進行優化。

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.Socket; 

/** 
     @author Mir Shafiqul Islam &lt;[email protected]&gt; 

*/ 
public class TestClient 
{ 

    /** 

     @param args 

    */ 
    public static void main(String[] args) throws Exception 
    { 
     // Open the socket 
     Socket socket = new Socket("localhost", 25143); 
     // Get a buffered reader 
     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     // At this point it is too early to read. So it most likely return false 
     System.out.println("Buffer Reader ready? " + reader.ready()); 
     // StringBuilder to hold the response 
     StringBuilder sb = new StringBuilder(); 
     // Indicator to show if we have started to receive data or not 
     boolean dataStreamStarted = false; 
     // How many times we went to sleep waiting for data 
     int sleepCounter = 0; 
     // How many times (max) we will sleep before bailing out 
     int sleepMaxCounter = 50; 
     // Sleep max counter after data started 
     int sleepMaxDataCounter = 3; 
     // How long to sleep for each cycle 
     int sleepTime = 50; 
     // Start time 
     long startTime = System.currentTimeMillis(); 
     // This is a tight loop. Not sure what it will do to CPU 
     while(true) { 
      if (reader.ready()) 
      { 
       sb.append((char) reader.read()); 
       // Once started we do not expect server to stop in the middle and restart 
       dataStreamStarted = true; 
      } else { 
       Thread.sleep(sleepTime); 
       if (dataStreamStarted && (sleepCounter >= sleepMaxDataCounter)) { 
        System.out.println("Reached max sleep time of " + (sleepMaxDataCounter*sleepTime) + " ms after data started"); 
        break; 
       } else { 
        if (sleepCounter >= sleepMaxCounter) { 
         System.out.println("Reached max sleep time of " + (sleepMaxCounter*sleepTime) + " ms. Bailing out"); 
         // Reached max timeout waiting for data. Bail.. 
         break; 
        } 
       } 
       sleepCounter++; 
      } 

     } 
     long endTime = System.currentTimeMillis(); 

     System.out.println(sb.toString()); 
     System.out.println("Time " + (endTime-startTime)); 
    } 

}