我有一个简单的TCP服务器:
public class ServerSocketRunner {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9000);
while (true) {
Socket socket = serverSocket.accept();
new Thread(() -> {
System.out.println("New client connected");
try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
String inputLine, outputLine;
do {
inputLine = in.readLine();
System.out.print("Received: " + inputLine);
String serverResponse = "Message Received: " + now();
System.out.println("Sending: " + serverResponse);
out.println(serverResponse);
} while (!"bye".equals(inputLine));
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
和客户
public class ClientRunner {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("localhost", 9000);
Scanner input = new Scanner(socket.getInputStream());
PrintWriter output = new PrintWriter(socket.getOutputStream(), true)) {
Scanner userEntry = new Scanner(System.in);
String message, response;
do {
System.out.print("Enter message: ");
message = userEntry.nextLine();
output.println(message);
response = input.nextLine();
System.out.println("\nSERVER> " + response);
} while (!message.equals("bye"));
}
}
}
客户端发送用户类型的消息,服务器以“收到消息”和时间戳作为响应。除一种情况外,其他所有方法都运行良好。如果我使用IntelliJ关闭客户端,请关闭,然后单击“断开连接”按钮
服务器无限期开始打印
Received: nullSending: Message Received: 2019-10-03T14:44:36.962
Received: nullSending: Message Received: 2019-10-03T14:44:36.962
Received: nullSending: Message Received: 2019-10-03T14:44:36.962
...
所以它不断收到换行符的空消息。断开连接行为已解释here
断开连接(如果可用)--->如果选择此选项,则正在运行的进程将断开连接。
因此,这意味着断开连接使进程继续运行,但是IntelliJ将不再附加到该进程。但这仍然不能解释为什么服务器不断收到新的(空)消息。
任何人都可以解释这种行为吗?
客户端已断开连接,因此客户端与服务器之间的连接已断开。但是您的代码无法处理该问题。当连接断开时,它构成“流的末尾”,BufferedReader
的readLine
函数返回null
。这就是它在输出中告诉您的内容:
Received: null [...]
您需要检查null
返回值并中断循环。
inputLine = in.readLine();
if (inputLine == null) {
System.out.print("Client disconnected. Leaving\n");
break;
}
客户端和服务器均应执行该测试。在真实的网络中,您永远不知道对等方何时消失。
请参见https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html#readLine--处的文档(返回: ... 如果已到达流的末尾,则为null]]
((我不完全知道IntelliJ在这里发生了什么,但是显然服务器线程仍在运行。服务器和客户端大概在单独的子进程或线程中运行。)