2016-11-03 2 views
7

Я пытаюсь реализовать простое клиент-серверное приложение в Java.Java while (true) цикл выполняется только один раз внутри потока

Вот код:

Client.java

public class Client implements Runnable { 
    private String hostName; 
    private int portNumber; 
    private String message; 

    private Socket socket; 
    private PrintWriter writer; 
    private BufferedReader reader; 

    public Client(String hostName, int portNumber, String message) { 
     this.hostName = hostName; 
     this.portNumber = portNumber; 
     this.message = message; 
    } 

    public void connect() { 
     try { 
      socket = new Socket(hostName, portNumber); 
      writer = new PrintWriter(socket.getOutputStream(), true); 
      reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

      writer.println(message); 
     } catch (UnknownHostException e) { 
      System.err.println("Could not resolve the host name '" + hostName + "'."); 
     } catch (IOException e) { 
      System.err.println("Could not get the I/O for the connection to '" + hostName + "'."); 
     } 
    } 

    private void listenForMessages() { 
     while (true) { 
      try { 
       System.out.println("In loop!"); 
       String line; 
       while ((line = reader.readLine()) != null) { 
        System.out.println(line); 
       } 
      } catch (IOException e) { 
       System.err.println(e.getMessage()); 
      } 
     } 
    } 

    public void run() { 
     connect(); 
     listenForMessages(); 
    } 
} 

Server.java

public class Server implements Runnable { 
    private int portNumber; 
    private String message; 

    private ServerSocket serverSocket; 
    private Socket clientSocket; 
    private PrintWriter writer; 
    private BufferedReader reader; 

    public Server(int portNumber, String message) { 
     this.portNumber = portNumber; 
     this.message = message; 
    } 

    private void listen() { 
     try { 
      serverSocket = new ServerSocket(portNumber); 
     } catch (IOException e) { 
      System.err.println(e.getMessage()); 
     } 

     while (true) { 
      try { 
       clientSocket = serverSocket.accept(); 
       writer = new PrintWriter(clientSocket.getOutputStream(), true); 
       reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 

       String line; 
       while ((line = reader.readLine()) != null) { 
        System.out.println(line); 
       } 

       writer.println(message); 
      } catch (IOException e) { 
       System.err.println(e.getMessage()); 
       break; 
      } 
     } 
    } 

    public void run() { 
     listen(); 
    } 
} 

И это главный класс:

public class Test { 
    public static void main(String[] args) { 
     Client client = new Client("localhost", 4444, "Hello from client!"); 
     Server server = new Server(4444, "Hello from server!"); 

     Thread serverThread = new Thread(server); 
     serverThread.start(); 

     Thread clientThread = new Thread(client); 
     clientThread.start(); 
    } 
} 

Логика код прост: как клиент, так и rver ждут сообщений внутри цикла while(true).

Цикл while внутри метода listen сервера выполняется просто отлично. Однако внутри метода listenForMessages цикл, кажется, выполняется только один раз. Я вижу только один «In loop», напечатанный на экране.

Можете ли вы выяснить, в чем проблема?

Спасибо заранее!

+0

Вы можете использовать отладчик? –

+0

Ну, я использую простой текстовый редактор, и я не знаю, как использовать отладчик из командной строки. –

+2

Боковое примечание: и вы уверены, что не забыли какие-либо из ваших исключений? Видите ли, ваш код просто ** печатает ** на исключениях; но затем он просто пытается продолжить то, что он делает. Подумайте, просто ** сбой ** на исключения! – GhostCat

ответ

6

Однако внутри метода listenForMessages, цикл, кажется, выполняется только один раз. Я вижу только один «In loop», напечатанный на экране.

На самом деле это не потому, что цикл выполняется только один раз, это просто потому, что reader.readLine() сделает текущий поток в состояние ожидания до тех пор, пока не получит всю строку и здесь, если вы проверить код Server, он читает первый и читается в бесконечном цикле, так как reader.readLine() возвращает только null в конце потока, поэтому, когда сокет будет закрыт в этом случае.

Если вы хотите реализовать какой-то пинг-понг между клиентом и сервером, просто читать то написать на одной стороне и читать и писать, а другая сторона в следующем:

Client код:

public void connect() { 
    try { 
     socket = new Socket(hostName, portNumber); 
     writer = new PrintWriter(socket.getOutputStream(), true); 
     reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

    } catch (UnknownHostException e) { 
     System.err.println("Could not resolve the host name '" + hostName + "'."); 
    } catch (IOException e) { 
     System.err.println(
      "Could not get the I/O for the connection to '" + hostName + "'." 
     ); 
    } 
} 

private void listenForMessages() { 
    while (true) { 
     try { 
      System.out.println("In loop!"); 
      // Write the message for the server 
      writer.println(message); 
      // Read the message from the server 
      System.out.println(reader.readLine()); 
     } catch (IOException e) { 
      System.err.println(e.getMessage()); 
     } 
    } 
} 

Server код:

while (true) { 
    try { 
     clientSocket = serverSocket.accept(); 
     writer = new PrintWriter(clientSocket.getOutputStream(), true); 
     reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 

     while (true) { 
      // Read the message from the client 
      System.out.println(reader.readLine()); 
      // Write the message for the client 
      writer.println(message); 
     } 


    } catch (IOException e) { 
     System.err.println(e.getMessage()); 
     break; 
    } 
} 

Выход:

In loop! 
Hello from client! 
Hello from server! 
In loop! 
Hello from client! 
Hello from server! 
... 
+1

Спасибо вам большое! Теперь все ясно. –