是什么导致 java.net.SocketException:关闭客户端后连接重置?
What's causing java.net.SocketException: Connection reset after closing client?
我正在写 server/client 申请学校。
每次我关闭客户端,服务器都会抛出'java.net.SocketException: Connection reset'。我想,我必须在关闭 JavaFX-window 之前关闭客户端中的套接字,但是在哪里呢?或者你怎么看?
我看到过类似的问题,但我不知道如何在我的程序中正确实现它。
异常:
20:05:27.132 [Thread-2] ERROR OnlineBank - java.net.BindException: Address already in use: JVM_Bind
19:51:06.580 [Thread-1] ERROR ServerHandler - java.net.SocketException: Connection reset
19:51:06.580 [Thread-2] ERROR ServerHandler - java.net.SocketException: Connection reset
我的程序:
private MyProgramm() {
server = new MyServer(Constants.REMOTE_PORT);
try
server.start();
} catch (ClassNotFoundException | IOException e) {
logger.error(e);
}
}
我的服务器:
public void start() throws ClassNotFoundException, IOException {
try {
serverSocket = new ServerSocket(this.port);
while (true) {
Socket client = serverSocket.accept();
logger.debug(getClass().getName() + " accepts");
Thread threadHandler = new Thread(new ServerHandler(client));
threadHandler.start();
}
} finally {
if (serverSocket != null) {
serverSocket.close();
}
}
}
服务器处理程序:
@Override
public void run() {
try (InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
ObjectInputStream oin = new ObjectInputStream(in);
ObjectOutputStream oos = new ObjectOutputStream(out)) {
while (true) {
try {
Object receivedObject = oin.readObject();
handleReceivedObject(oos, receivedObject);
} catch (ClassNotFoundException e) {
logger.error(e);
break;
}
}
} catch (IOException e) {
logger.error(e);
}
}
主客户端:
public class MainClient extends Application {
private static Client client;
public static void main(String[] args) {
launch(args);
try {
client = new Client();
} catch (IOException e) {
logger.error(e);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/welcome.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
// to avoid NullPointerException
if (Client != null && Client.getSocket() != null) {
Client.getSocket().close();
}
}
}
客户:
public class Client {
private Socket socket;
public Client(String remoteHost, int port) throws UnknownHostException, IOException {
if (getSocket() == null) {
socket = new Socket(remoteHost, port);
}
}
public Client() throws UnknownHostException, IOException {
this(Constants.REMOTE_HOST, Constants.REMOTE_PORT);
}
public Socket getSocket() {
return socket;
}
}
你是对的。在退出客户端之前,您必须正确关闭客户端套接字。否则操作系统可能会重置连接而不是关闭它。我不是 Android 人,我无法建议您应该将此闭包放在哪里。
你的服务器也有问题。它需要在读取循环中捕获 EOFException
并静默中断。目前您没有正确处理流的结尾:您将通过 catch (EOFException )
捕获它并将其记录为错误,但事实并非如此。
我正在写 server/client 申请学校。
每次我关闭客户端,服务器都会抛出'java.net.SocketException: Connection reset'。我想,我必须在关闭 JavaFX-window 之前关闭客户端中的套接字,但是在哪里呢?或者你怎么看?
我看到过类似的问题,但我不知道如何在我的程序中正确实现它。
异常:
20:05:27.132 [Thread-2] ERROR OnlineBank - java.net.BindException: Address already in use: JVM_Bind
19:51:06.580 [Thread-1] ERROR ServerHandler - java.net.SocketException: Connection reset
19:51:06.580 [Thread-2] ERROR ServerHandler - java.net.SocketException: Connection reset
我的程序:
private MyProgramm() {
server = new MyServer(Constants.REMOTE_PORT);
try
server.start();
} catch (ClassNotFoundException | IOException e) {
logger.error(e);
}
}
我的服务器:
public void start() throws ClassNotFoundException, IOException {
try {
serverSocket = new ServerSocket(this.port);
while (true) {
Socket client = serverSocket.accept();
logger.debug(getClass().getName() + " accepts");
Thread threadHandler = new Thread(new ServerHandler(client));
threadHandler.start();
}
} finally {
if (serverSocket != null) {
serverSocket.close();
}
}
}
服务器处理程序:
@Override
public void run() {
try (InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
ObjectInputStream oin = new ObjectInputStream(in);
ObjectOutputStream oos = new ObjectOutputStream(out)) {
while (true) {
try {
Object receivedObject = oin.readObject();
handleReceivedObject(oos, receivedObject);
} catch (ClassNotFoundException e) {
logger.error(e);
break;
}
}
} catch (IOException e) {
logger.error(e);
}
}
主客户端:
public class MainClient extends Application {
private static Client client;
public static void main(String[] args) {
launch(args);
try {
client = new Client();
} catch (IOException e) {
logger.error(e);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/welcome.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
// to avoid NullPointerException
if (Client != null && Client.getSocket() != null) {
Client.getSocket().close();
}
}
}
客户:
public class Client {
private Socket socket;
public Client(String remoteHost, int port) throws UnknownHostException, IOException {
if (getSocket() == null) {
socket = new Socket(remoteHost, port);
}
}
public Client() throws UnknownHostException, IOException {
this(Constants.REMOTE_HOST, Constants.REMOTE_PORT);
}
public Socket getSocket() {
return socket;
}
}
你是对的。在退出客户端之前,您必须正确关闭客户端套接字。否则操作系统可能会重置连接而不是关闭它。我不是 Android 人,我无法建议您应该将此闭包放在哪里。
你的服务器也有问题。它需要在读取循环中捕获 EOFException
并静默中断。目前您没有正确处理流的结尾:您将通过 catch (EOFException )
捕获它并将其记录为错误,但事实并非如此。