Java 我的输入流如何';s消息在定期接收数据时从不为空?

Java 我的输入流如何';s消息在定期接收数据时从不为空?,java,loops,sockets,client-server,inputstream,Java,Loops,Sockets,Client Server,Inputstream,我想拥有服务器-客户端关系。一旦客户端连接到服务器,服务器每1.5秒向客户端发送一条消息。为了简单起见,服务器不处理来自客户端的消息。在客户端代码中,我想使用System.In向服务器发送消息(这并不意味着什么),当我发送消息时,我想读取服务器的响应(来自服务器的所有累积消息)。代码不是片段,而是“真正的代码” 客户端: public class ClientClass { public static final String IP_ADDRESS = "127.0.0.1&q

我想拥有服务器-客户端关系。一旦客户端连接到服务器,服务器每1.5秒向客户端发送一条消息。为了简单起见,服务器不处理来自客户端的消息。在客户端代码中,我想使用
System.In
向服务器发送消息(这并不意味着什么),当我发送消息时,我想读取服务器的响应(来自服务器的所有累积消息)。代码不是片段,而是“真正的代码”

客户端:

public class ClientClass {
    public static final String IP_ADDRESS = "127.0.0.1";
    public static final int PORT = 9090;

    public static void main (String[] args) throws IOException {
        Socket socket = new Socket (IP_ADDRESS,PORT);
        PrintWriter output = new PrintWriter (socket.getOutputStream (),true);
        BufferedReader input = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
        BufferedReader keyboard = new BufferedReader (new InputStreamReader (System.in));

        while (true){
            System.out.println ("Enter message you want to send to server:");
            String msg = keyboard.readLine ();
            output.println (msg);

            String serverResponses = input.readLine ();
            while (serverResponses!=null){
                System.out.println (serverResponses);
                serverResponses=input.readLine ();
            }
        }
    }
}
public class ServerClass {
    public static int PORT = 9090;

    public static void main (String[] args) throws IOException, InterruptedException {
        ServerSocket server = new ServerSocket (PORT);
        Socket client = server.accept ();
        PrintWriter output = new PrintWriter (client.getOutputStream (),true);
        while (true){
            output.println ("hello from server");
            Thread.sleep (1500);
        }
    }
}
服务器:

public class ClientClass {
    public static final String IP_ADDRESS = "127.0.0.1";
    public static final int PORT = 9090;

    public static void main (String[] args) throws IOException {
        Socket socket = new Socket (IP_ADDRESS,PORT);
        PrintWriter output = new PrintWriter (socket.getOutputStream (),true);
        BufferedReader input = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
        BufferedReader keyboard = new BufferedReader (new InputStreamReader (System.in));

        while (true){
            System.out.println ("Enter message you want to send to server:");
            String msg = keyboard.readLine ();
            output.println (msg);

            String serverResponses = input.readLine ();
            while (serverResponses!=null){
                System.out.println (serverResponses);
                serverResponses=input.readLine ();
            }
        }
    }
}
public class ServerClass {
    public static int PORT = 9090;

    public static void main (String[] args) throws IOException, InterruptedException {
        ServerSocket server = new ServerSocket (PORT);
        Socket client = server.accept ();
        PrintWriter output = new PrintWriter (client.getOutputStream (),true);
        while (true){
            output.println ("hello from server");
            Thread.sleep (1500);
        }
    }
}
//我的评论:
readLine()
客户端中的方法是阻塞的,所以在我真正从键盘读取某些内容之前,我无法读取服务器的消息。这就是为什么我要循环“拾取”来自
inputStream
的所有行。我希望在读取所有行之后,变量
stringResponses
null从内部while循环中断。然后我想我会得到一个打印到控制台的“输入您想要发送到服务器的消息”在外循环中找到。不幸的是,我的代码从来没有从内部while循环中断过,我想知道为什么。当我每1.5s写入一个流时,这意味着有足够的时间使它为null并从循环中中断,它如何从不null

实际产量:

Enter message you want to send to server:
hey! //this is what I typed
hello from server
hello from server
hello from server
//these three popped immediately, as they accumulated.
hello from server
hello from server
hello from server
hello from server
//keeps printing "hello from server" every 1.5s and never comes back to "enter your message" -WHY?

readLine
在流的末尾返回null。因为服务器套接字未关闭。它在您的内部循环中永远不会为空

链接-

包含行内容的字符串,不包括任何 行终止字符,如果流的结尾已被删除,则为null 达到

当在键盘对象上的循环中调用
readLine
时,您希望出现什么行为

String msg = keyboard.readLine();
while(msg != null)
   msg = keyboard.readLine();
这也将继续从
系统中获取输入。循环永远不会结束

解决 正如上面从java文档中引用的,
readLine
方法块用于输入。这就是为什么延迟服务器响应没有任何效果。该方法仅在流的末尾返回
null

解决方案1-利用就绪方法

当读取方法必须等待输入数据时,
ready
方法返回false。由于服务器代码休眠1.5秒,此方法在此期间应返回false。 这种方法的缺点是,如果服务器没有按时完成所有响应行,那么收集所有服务器响应的内部循环就会中断

while (true){
        System.out.println ("Enter message you want to send to server:");
        String msg = keyboard.readLine ();
        output.println (msg);

        String serverResponses = input.readLine ();
        System.out.println (serverResponses);

        while (input.ready()){
           serverResponses=input.readLine ();
           System.out.println (serverResponses);
        }
    }
解决方案2-服务器发送总行数

如果服务器知道行的总数,那么可以将其作为流中的第一行发送。根据总行数,客户机代码可以读取这么多行。这种方法的缺点是必须在服务器响应中添加额外的行

while (true){
        System.out.println ("Enter message you want to send to server:");
        String msg = keyboard.readLine ();
        output.println (msg);

        Integer linesCount = Integer.parseInt(input.readLine ());
        for (int i=0; i< linesCount; i++){
            String serverResponses=input.readLine ();
            System.out.println (serverResponses);
            
        }
    }
while(true){
System.out.println(“输入要发送到服务器的消息:”);
字符串msg=keyboard.readLine();
output.println(msg);
整数linescont=Integer.parseInt(input.readLine());
对于(int i=0;i
我注意到它永远不会结束,但如何结束呢?当我读取了所有可能的行并且没有更多行时,它应该返回null并退出循环。它怎么不这样做?@Markus这就是它的工作原理。应为
null
不是一个选项。如果服务器发送的第一条消息是总行数,那么这会解决您的问题吗。然后你可以循环阅读这些行。请原谅我的困惑,因为我是一个初学者,但它仍然不是100%清楚。是的,如果到达流的末尾,我将得到
null
。但我运行了一个小测试,我也得到了
null
,即使并没有更多的行要读取,流也并没有关闭。在我的例子中,代码中有一些地方可以获得
null
,因为没有更多的行可以读取。所以我还是不明白为什么它不从内部循环中断。你能帮忙吗?@Markus你能在你从
readLine
方法得到
null
的地方发布/分享你的测试吗?我见过有人在pastebin上分享代码。我个人没有这样做。Github也是一种选择。