Что вызывает java.net.SocketException: сброс соединения после закрытия клиента?

Я пишу серверное / клиентское приложение для школы.

Каждый раз, когда я закрываю клиент, сервер выдает исключение java.net.SocketException: Connection reset. Я думаю, мне нужно закрыть сокет в клиенте перед закрытием JavaFX-окна, но где? Или что вы думаете?

Я видел похожий вопрос, но не знаю, как правильно его реализовать в моей программе.

Исключение:

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);    
    }
}

MyServer:

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();
            }
        }

    }

ServerHandler:

@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);
        }
    }

MainClient:

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;
    }
}

person Jo Jay    schedule 01.07.2016    source источник
comment
@ControlAltDel Неверный дубликат. SocketException: Socket closed - это не то же самое, что SocketException: connection reset. Открыт снова.   -  person user207421    schedule 02.07.2016


Ответы (1)


Ты прав. Перед выходом из клиента необходимо правильно закрыть клиентский сокет. В противном случае операционная система может сбросить соединение вместо его закрытия. Не будучи сторонником Android, я не могу посоветовать вам, где следует разместить это закрытие.

У вашего сервера тоже проблема. Ему нужно поймать EOFException в цикле чтения и молча прервать его. В настоящее время вы неправильно обрабатываете конец потока: вы поймаете его через catch (EOFException ) и зарегистрируете как ошибку, чего на самом деле нет.

person user207421    schedule 02.07.2016