当 IntelliJ 断开客户端连接时,套接字输入流在 readLine 上连续返回 null
Socket input stream continuously returning null on readLine when Client disconnected by IntelliJ
我有一个简单的 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"));
}
}
}
客户端发送用户键入的消息,服务器以 [=38=] 和时间戳响应。除了一种情况外,一切都很好。如果我使用 IntelliJ 关闭客户端,关闭然后 "Disconnect" 按钮
服务器readLine
连续returnsnull
并打印
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
...
解释了 IntelliJ disconnect 行为 here
Disconnect (if available) ---> If this option is selected, the running process is disconnected.
因此,这意味着断开连接会保留进程 运行,但 IntelliJ 将不再附加到它。
这仍然不能解释为什么 readLine
不断返回 null
.
谁能解释这种行为?
客户端已断开连接,因此客户端与服务器的连接已断开。但是你的代码没有处理那个。当连接断开时,即构成 "end of stream" 和 BufferedReader
的 readLine
函数 returns null
。这正是它在输出中告诉您的内容:
Received: null [...]
您需要检查 null
return 值并跳出循环。
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-- 处的文档(Returns: ... 如果已到达流末尾,则为 null)
(我不知道这里的 IntelliJ 到底发生了什么,但显然服务器线程仍然是 运行。服务器和客户端大概是 运行 在单独的子进程或线程中。 )
我有一个简单的 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"));
}
}
}
客户端发送用户键入的消息,服务器以 [=38=] 和时间戳响应。除了一种情况外,一切都很好。如果我使用 IntelliJ 关闭客户端,关闭然后 "Disconnect" 按钮
服务器readLine
连续returnsnull
并打印
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
...
解释了 IntelliJ disconnect 行为 here
Disconnect (if available) ---> If this option is selected, the running process is disconnected.
因此,这意味着断开连接会保留进程 运行,但 IntelliJ 将不再附加到它。
这仍然不能解释为什么 readLine
不断返回 null
.
谁能解释这种行为?
客户端已断开连接,因此客户端与服务器的连接已断开。但是你的代码没有处理那个。当连接断开时,即构成 "end of stream" 和 BufferedReader
的 readLine
函数 returns null
。这正是它在输出中告诉您的内容:
Received: null [...]
您需要检查 null
return 值并跳出循环。
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-- 处的文档(Returns: ... 如果已到达流末尾,则为 null)
(我不知道这里的 IntelliJ 到底发生了什么,但显然服务器线程仍然是 运行。服务器和客户端大概是 运行 在单独的子进程或线程中。 )