while循环仅在第一个循环停止,然后继续无限期地运行

while循环仅在第一个循环停止,然后继续无限期地运行

问题描述:

该练习程序的目标仅仅是允许客户端连续发送用户通过输入并按下输入键并将其输出到控制台的消息串。第一次,Server.java中的String messageFromClient = in.readLine();似乎阻塞(调试器不会让我离开)。然而,在发送消息如“你好”之后,它会继续无阻挡地运行。while循环仅在第一个循环停止,然后继续无限期地运行

我一直在寻找这个了几个小时,但我想我只是没有看到解决方案的正确位置。

此链接Java InputStream blocking read可能是我发现的最接近的东西,可以帮助我。

Client.java

import java.io.*; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 
import java.net.*; 
import java.net.InetAddress; 
import java.util.Scanner; 

public class Client { 
    static Socket connectionToServer; 
    public static void main(String[] args) { 
     try{ 
      connectionToServer = new Socket("192.168.1.66", 6969); 
      InetAddress inetAddress = connectionToServer.getInetAddress(); 
      System.out.print(
        "Connection successful" + 
        "Connected to " + inetAddress.getHostAddress() + 
        "at " + inetAddress.getHostName() + "\n" 
      ); 

      while(true) { 
       String input = System.console().readLine(); 
       OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream()); 
       dOut.write(input, 0, input.length()); 
       //dOut.flush(); 
       dOut.close(); 
      } 

     } catch (IOException exception){ 
      System.out.print("Failed to create socket"); 
     } 

    } 
} 

Server.java

import java.io.*; 
import java.net.*; 

public class Server { 
    public static void main(String[] args) { 
     ServerSocket serverSocket; 
     try { 
      serverSocket = new ServerSocket(6969); 
      System.out.print("Server is up and running \n"); 
     } catch (IOException exception){ 
      serverSocket = null; 
      System.out.print("Cannot create ServerSocket"); 
     } 

     while (true){ 
      try { 
       System.out.print("Waiting from client."); 
       Socket socket = serverSocket.accept(); 
       Thread newClientSocket = new Thread(new ServerThread(socket)); 
       newClientSocket.start(); 
       System.out.print("New thread created"); 
      } catch (IOException exception){ 
       System.out.print("Failed to create socket"); 
      } 
     } 
    } 
} 
//////////////////////////////////////////////////////////// 
class ServerThread implements Runnable{ 
    private Socket socket; 
    //constructor 
    ServerThread(Socket socket){ 
     System.out.print("I am a new thread"); 
     this.socket = socket; 
    } 

    public void run(){ 
     while(true){ 
      try{ 
       System.out.print("Waiting for input."); 
       InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream()); 
       BufferedReader in = new BufferedReader(inputStreamReader); 
       String messageFromClient = in.readLine(); 
       System.out.print(messageFromClient); 
      } catch (IOException exception) { 
       System.out.print(exception); 
       break; 
      } 
     } 
    } 
} 

你不应该构建每次循环迭代新BufferedReader,因为BufferedReader将尝试完全填充缓冲区,并可能在第一行结束时读取数据 - 并且数据将丢失,因为您正在构建一个新的BufferedReader只有它的第一行。

将BufferedReader的构建移出循环,这应该会对您有所帮助。另外,请确保在完成后关闭套接字。

public void run() { 
    try { 
     try { 
      InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream()); 
      BufferedReader in = new BufferedReader(inputStreamReader); 
      while (true) { 
       System.out.print("Waiting for input."); 
       String messageFromClient = in.readLine(); 
       System.out.print(messageFromClient); 
      } 
     } finally { 
      socket.close(); 
     } 
    } catch (IOException exception) { 
     System.out.print(exception); 
     // TODO: handle exception 
    } 
} 

在发送端,你不应该关闭套接字的OutputStream中的每一行,因为一旦你关闭它,你不能用它了。并且您应该在字符串后面向服务器发送换行符,因为Console.readLine()方法未将其包含在其返回值中。

 OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream()); 
     while(true) { 
      String input = System.console().readLine() + "\n"; 
      dOut.write(input, 0, input.length()); 
     } 
     dOut.close(); 

到Console.ReadLine()不包括终止字符。 BufferedReader.readLine()块直到它得到一个终止换行符

更改此:

String input = System.console().readLine(); 

要这样:

String input = System.console().readLine() + System.lineSeparator();