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

时间:2016-09-16 04:20:12

标签: java serversocket

此练习程序的目标只是允许客户端通过键入和按下输入键连续发送用户输入的消息字符串并将其打印到控制台。第一次,Server.java中的String messageFromClient = in.readLine();似乎被阻塞(Debugger不会让我走出去)。然而,在向它发送“hello”之类的消息之后,它会不断地运行而不会阻塞。

我一直在搜索这个问题几个小时,但我想我只是没有找到适合解决方案的地方。

此链接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;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

Console.readLine()不包含终止字符。 BufferedReader.readLine()阻塞,直到它获得终止换行符

改变这个:

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

对此:

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

答案 1 :(得分:0)

你不应该为每个循环迭代构造一个新的BufferedReader,因为BufferedReader将尝试完全填充其缓冲区并且可能读取超出第一行的末尾 - 并且该数据将丢失,因为您在仅读取第一行后,正在构建 new 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();