2016-10-03 56 views
4

上個月我開始學習java,現在我正在嘗試編寫一個簡單的聊天程序,但是我遇到了一些奇怪的事情,我很好奇它背後的原因。使用Java進行簡單聊天的奇怪行爲

import java.io.*; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.Scanner; 

public class Server { 
public static void main(String[] args) throws IOException { 
    String text = ""; 
    ServerSocket ss = new ServerSocket(21025); 
    while (true){ 

     System.out.println("Waiting..."); 
     Socket s1 = ss.accept(); 
     System.out.println("Connection accepted from "+s1.getInetAddress()); 
     PrintStream pout = new PrintStream(s1.getOutputStream()); 
     pout.println("Connected to the server"); 

     new Thread(new Ricevitore(s1)).start(); 
    } 
    } 
} 

public class Ricevitore implements Runnable { 
String text = ""; 
Socket skt; 
public Ricevitore(Socket skt){ 
    this.skt = skt; 
} 
@Override 
public void run() { 
    while (!text.equalsIgnoreCase("end")) { 
     try { 
      InputStream in = skt.getInputStream(); 
      BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
      text = br.readLine(); 
      if (!text.equalsIgnoreCase("end")) 
      System.out.println(text); 
     } 
     catch (IOException e){} 
    } 
    } 
} 

public class Client { 
public static void main(String[] args) throws IOException { 

    //Create a socket 
    try (Socket s = new Socket("127.0.0.1", 21025)) { 
     String text=""; 
     while(!text.equalsIgnoreCase("end")) { 

      //Allows messages from server 
      InputStream in = s.getInputStream(); 
      BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
      if (br.ready()) { 
       Scanner server = new Scanner(br); 
       String testoServer = br.readLine(); 
       System.out.println(testoServer); 
      } 

      //Allows to send text to the server 
      OutputStream out = s.getOutputStream(); 
      PrintStream pout = new PrintStream(out); 

      Scanner tastiera = new Scanner(System.in); 
      text = tastiera.nextLine(); 
      pout.println(text); 

     } 
    } 
    } 
} 

這是當下完整的程序,我的問題是這樣的:因爲我想避免打印單詞「結束」關閉程序,我插

if (!text.equalsIgnoreCase("end")) 

,但在此之後,服務器不顯示消息「連接到服務器」,除非我首先通過客戶端輸入內容。 如果我註釋,如果聲明,「連接接受」和「連接到服務器」的消息都打印在預期的同一時間。 我不知道我的問題是否清楚,我對學習爲什麼會發生這樣的事情感興趣。

如果還有其他你認爲是錯誤的東西,我會很樂意在這裏談論它們。

+0

可能與問題無關,但每個流只需要一個'Scanner'對象。你可以在循環之外聲明它。 –

+1

你的意思是在客戶端2?一個從鍵盤輸入輸入,另一個從服務器輸入,我可以只用一個來完成這兩個任務嗎? – Waterblade85

+1

每個流一個。所以,一個用於來自套接字的輸入,另一個用於'System.in'。 getInputStream()'和'getOutputSteam()'可以(或者應該)在while循環之外被調用 –

回答

1

我只有瘋狂的猜測,儘管看起來很可能。

在客戶端,如果br.ready()返回true,則從服務器讀取消息。可能發生這個函數返回false,並且客戶端去等待用戶的輸入。

從客戶端向服務器發送消息後,客戶端重複測試,現在從服務器獲取消息。

我無法解釋爲什麼在服務器代碼中刪除if (!text.equalsIgnoreCase("end"))使問題消失。直到您從客戶端發送消息纔會執行該行。

所以我認爲這只是一個巧合。涉及兩個過程,結果取決於代碼在任一過程中的執行速度。

我跑了你的例子很多次,並且一旦我沒有收到來自服務器的問候,即使上面的if在它的位置。


爲您的代碼的一般建議:你不需要在每次迭代創建輸入/輸出流,以及Scanner,你應該這樣做只有一次。

要結束通信會話,只要您收到來自用戶的end即可關閉客戶端中的PrintStream。您的服務器將從br.readLine()獲得null。此時,您關閉br並完成run()