2017-08-14 85 views
0

我有一個看起來客戶端代碼,如:Socket的PrintWriter的不發,直到關閉

Socket s = new Socket(server.getHostName(), server.getPort()); 
PrintWriter p = new PrintWriter(s.getOutputStream()); 
p.println(message); 
p.flush(); 
s.shutdownOutput(); 

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
String newLine; 
StringBuffer response = new StringBuffer(); 
while((newLine = br.readLine()) != null) 
    response.append(newLine); 
System.out.println(response.toString()); 
p.close(); 
br.close(); 

和服務器代碼,看起來像:

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
String nextLine; 
StringBuffer request = new StringBuffer(); 

System.out.println("Starting read...."); 
String nextline; 
while((nextline = br.readLine()) != null){ 
    System.out.println(nextline); 
    request.append(nextline); 
} 
System.out.println("Message recived!!"); 
System.out.println("Request: " + request); 

PrintWriter p = new PrintWriter(s.getOutputStream()); 
p.println("Hello, fileclient!"); 
System.out.println("Message sent!!"); 

p.close(); 
br.close(); 

在我把線s.shutDownInput()服務器代碼會掛在br.readLine().我設法解決的方法是關閉PrintWriter一些方法,無論是通過p.close()還是通過當前的方式,其中不關閉 像關閉PrintWriter通過p.close()呢。之後,客戶端和服務器之間的交互是完美的。

爲什麼PrintWriterBufferedReader不能發送/接收,直到PrintWriter以某種方式關閉?

+1

你爲什麼期望它?緩衝是正常的,關閉流迫使它沖洗其內容。 –

+0

我猜他想讓套接字打開,以便發送更多的數據。 –

+0

就像現在的筆記一樣,您應該使用** try-with-resources **自動並正確地關閉像'Socket'這樣的資源。它看起來像這樣:'try(Socket s = new Socket(...)){your code}'。 Java在到達結尾(關閉'}')時自動關閉'try(...)'部分中定義的所有資源。這可以通過實現'AutoCloseable'的一切來完成,這些類有很多類:https://docs.oracle.com/javase/8/docs/api/java/lang/Au​​toCloseable.html – Zabuza

回答

1

PrintWriter沒有任何關係。這是您的應用程序協議錯誤。

  • 服務器正在循環讀取行直到流結束。

  • 客戶端正在發送一行,然後不關閉套接字,因此沒有發送結束流(直到您添加關閉)。

  • 服務器正在響應。

  • 客戶正在閱讀。

所以直到服務器獲取圈外的客戶端不讀什麼,而服務器沒有擺脫它的循環,因爲客戶端是讀不打烊。

所以下定決心吧。服務器應該只能讀一行。

+0

你和@John Bollinger都是對的。我不知道br.readLine()讀取直到流結束。我以爲它一直走下去,直到沒有更多的線被讀取。非常感謝你!對於將來的人,請閱讀,直到br.readLine()等於null,或者如果它收到並且單個'q'。 –

+0

「readLine()」的行爲已記錄在案。它不讀取直到流結束,但是你的代碼通過循環直到它返回null,它在err結束時返回null。 – EJP

1

雙方的表現與你告訴他們做的完全相同。特別是,你指示服務器專門去詳細閱讀客戶端分派任何響應之前發送:

String nextline; 
    while((nextline = br.readLine()) != null){ 
     System.out.println(nextline); 
     request.append(nextline); 
    } 

明白,不會停止讀書,直到錯誤或末,其中的結束是很重要的在套接字上的流對應於另一端已經關閉並且所有數據都已被讀取。換句話說,在分派響應之前,服務器等待整個對話的結束,而不是單個消息的結束。

因爲這顯然不是你想要的,所以你需要在服務器上實現一個不同的策略來確定何時處理到目前爲止收到的數據併發送響應。如果您可以確信您的郵件不會包含內部換行符,那麼這可能與發送每個響應之前服務器僅執行一個br.readLine()一樣簡單。

+0

非常感謝您的幫助。你和EJP非常有幫助。就像我上面所說的,我認爲它一直等到沒有更多的東西要被讀取,而不是直到流尾。我通過聽一個'q'然後處理請求來解決這個問題。 –

相關問題