Что сделать, когда ServerSocket бросает IOException и поддерживающий в рабочем состоянии сервер

В основном я хочу создать горный сервер тела.

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
    } catch (IOException e) {
        e.printStackTrace();
        // NOW WHAT?
    }
}

В блоке IOException, что сделать? Сокет Сервера в отказе, таким образом, он должен быть воссоздан? Например, ожидайте несколько секунд и затем

serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);

Однако, если сокет сервера все еще в порядке, то жаль, чтобы закрыть его и уничтожить все ранее принятые соединения, которые все еще связываются.

Править: После некоторых ответов, здесь моя попытка иметь дело с IOException. Реализация гарантировала бы продолжение сервера и только воссоздавать сокет сервера когда только необходимый?

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
        bindExceptionCounter = 0;
    } catch (IOException e) {
        e.printStackTrace();

        recreateServerSocket();
    }
}

private void recreateServerSocket() {
    while (keepRunning) {
        try {
            logger.info("Try to re-create Server Socket");
            ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);

            // No exception thrown, then use the new socket.
            serverSocket = socket;
            break;
        } catch (BindException e) {
            logger.info("BindException indicates that the server socket is still good.", e);
            bindExceptionCounter++;

            if (bindExceptionCounter < 5) {
                break;
            }
        } catch (IOException e) {
            logger.warn("Problem to re-create Server Socket", e);
            e.printStackTrace();

            try {
                Thread.sleep(30000);
            } catch (InterruptedException ie) {
                logger.warn(ie);
            }
        }
    }
}    
5
задан s5804 14 June 2010 в 10:39
поделиться

4 ответа

Если есть сомнения, вы можете попробовать воссоздать серверный сокет, используя тот же порт. Если сокет был закрыт, создание будет успешным, и вы сможете продолжить обработку новых подключений. Старые соединения пропали, но это вне вашего контроля, так как сокет был закрыт. Если сокет не был закрыт, создание нового экземпляра не удастся, поскольку порт все еще используется, что вы можете просто игнорировать, т.е. не заменять текущую ссылку на серверный сокет.

В общем, клиенты также должны предполагать, что соединение будет прервано и потребуется повторное соединение. Другими словами, не только сервер должен быть надежным - клиенты также должны предвидеть ошибки подключения и повторно подключаться.

4
ответ дан 14 December 2019 в 04:30
поделиться

Вы можете получить исключение IOException в accept (), если сокет сервера закрыт (вами) или у вас закончились ресурсы, например файловые ручки. В любом случае, вы мало что можете с этим поделать. Если serverSocket закрыт (вы можете проверить это), у вас, вероятно, была веская причина для этого. Если у вас закончатся ресурсы, вам придется либо увеличить лимит ресурсов, что потребует перезапуска вашего приложения, либо у вас возникнет утечка ресурсов.

2
ответ дан 14 December 2019 в 04:30
поделиться

Убедитесь, что вы различаете разные IOException , которые вы можете получить. Это исключение при создании соединения? Является ли это исключением, если соединение уже установлено?

Единственный код, который вы указали, - это accept () ing. Вообще говоря, исключение IOException обычно означает ошибку на любом уровне физической сети.

Вероятно, лучшее резервное поведение, которое вы можете реализовать, - это дождаться определенного кванта времени, а затем попытаться восстановить соединение. Предположим, вы, скорее всего, не сможете повторно подключиться, поскольку вы потеряли сетевое соединение более чем на временный период. Убедитесь, что вы справляетесь с этим изящно. Как упоминалось в @mdma, это также должно поддерживаться вашими клиентами.

1
ответ дан 14 December 2019 в 04:30
поделиться

Однако, если сокет сервера все еще ОК, тогда жалко закрывать и убить все ранее принятые связи, которые все еще общение.

Обратите внимание, что закрытие серверного сокета НЕ закрывает ранее принятые соединения. Как только соединение было принято, он живет отдельной, радостной жизнью в другом порту.

1
ответ дан 14 December 2019 в 04:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: