2014-10-26 40 views
0

我正在用Java編寫一個簡單的服務器,並且我能夠從服務器端的客戶端檢索傳入數據,但由於2000毫秒超時而無法在客戶端進行傳入。任何人都知道爲什麼這次超時?Java套接字超時:損壞的管道

這是服務器的代碼:

private static void listen() throws IOException { 
    while(true) { 
     Socket clientSocket = serverSocket.accept(); 
     StringBuilder bufferedStringInput = new StringBuilder(); 
     CharBuffer cbuf = CharBuffer.allocate(4096); 
     try { 
      InputStream is = clientSocket.getInputStream(); 
      BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF8")); 
      int noCharsLeft = 0; 
      while ((noCharsLeft = br.read(cbuf)) != -1) { 
       char[] arr = new char[noCharsLeft]; 
       cbuf.rewind(); 
       cbuf.get(arr); 
       bufferedStringInput.append(arr); 
       cbuf.clear(); 
      }   
      System.out.println(bufferedStringInput.toString()); 
     } catch (IOException e) { 
      System.out.println("Error received client data: " + e.getMessage()); 
     } 

     String message = "Hello client"; 
     try { 
      PrintWriter out = new PrintWriter(clientSocket.getOutputStream()); 
      out.print(message); 
     } catch (IOException e) { 
      System.out.println("Error getting output stream from client: " + e.getMessage()); 
     } 
     clientSocket.close();  
    } 
} 

回答

2

您正在閱讀的輸入,直到流,只發生在同行關閉連接的結束,那麼你試圖寫它,所以當然你會得到一個破損的管道。沒有意義。你只需要閱讀輸入,直到你有一個完整的請求,不管你的協議是什麼意思。

這裏有潛伏的其他問題:

  • 如果客戶端代碼使用readLine(),你不發送行結束符:使用println(),print(),並關閉PrintWriter,不只是客戶端套接字。

  • cbuf.rewind()/get()/clear()應該cbuf.flip()/get()/compact().

  • 但它會更有意義,直接讀入一個char[] cbuf = new char[8192];陣列,然後bufferedStringInput.append(cbuf, 0, noCharsLeft),,忘了CharBuffer乾脆。目前數據拷貝過多。

  • noCharsLeft是該變量的不良名稱。這是一個讀數。

+0

謝謝@EJP,我現在要解決這個問題。但爲什麼'compact()'優先於'clear()'? – cbrad 2014-10-27 01:26:46

+0

這是一個標準的習慣用法:'flip(),get(),compact()。'以防萬一你沒有'get()'例如。這在寫作時尤其適用。 – EJP 2014-10-27 04:32:05