Сервер Java TCP/IP неправильно закрывает соединения

Я создал MMO для телефона Android и использую сервер Java с сокетами TCP/IP. Обычно все работает нормально, но примерно через день, когда клиенты входят и выходят из сети, моя сеть начинает сильно тормозить, даже если клиенты не подключены. NETSTAT не показывает затяжных соединений, но очевидно, что происходит что-то ужасно неправильное.

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

    public final void disconnect()
{
    Alive = false;
    Log.write("Disconnecting " + _socket.getRemoteSocketAddress());
    try
    {
        _socket.shutdownInput();
    }
    catch (final Exception e)
    {
        Log.write(e);
    }
    try
    {
        _socket.shutdownOutput();
    }
    catch (final Exception e)
    {
        Log.write(e);
    }
    try
    {
        _input.close();
    }
    catch (final Exception e)
    {
        Log.write(e);
    }
    try
    {
        _output.close();
    }
    catch (final Exception e)
    {
        Log.write(e);
    }
    try
    {
        _socket.close();
    }
    catch (final Exception e)
    {
        Log.write(e);
    }
}

_input и _output — это BufferedInputStream и BufferedOutputStream, порожденные из сокета. Согласно документации, вызовы shutdownInput() и shutdownOutput() не должны быть необходимы, но я бросаю на это все, что могу.

Я создаю экземпляры сокетов с настройками по умолчанию — я не трогаю soLinger, KeepAlive, noDelay или что-то в этом роде. У меня не установлены тайм-ауты для отправки/получения. Я пытался использовать WireShark, но ничего необычного не обнаружил, как и NETSTAT.

Я очень отчаянно нуждаюсь в ответах на этот вопрос. Я приложил много усилий к этому проекту и разочарован тем, что кажется серьезным скрытым недостатком в реализации TCP по умолчанию в Java.


person jysend    schedule 03.12.2010    source источник
comment
Должен добавить, что все клиенты отключаются через 2 минуты бездействия. Нет проблем с заблокированными потоками Receive() от автоматически отключенных клиентов.   -  person jysend    schedule 03.12.2010
comment
Что произойдет, если вы просто перезапустите серверный процесс вместо перезагрузки? Да, вы можете использовать jvisualvm для мониторинга использования памяти и сбора мусора. Недостаток памяти гораздо более вероятен, чем что-либо с сокетами, особенно с учетом того, что netstat говорит, что все в порядке.   -  person Hendrik Brummermann    schedule 05.12.2010
comment
что вы имеете в виду, когда говорите, что моя сеть сильно тормозит - что именно тормозит?   -  person SimonJ    schedule 05.12.2010


Ответы (2)


Избавьтесь от shutdownInput() и shutdownOutput() и всех закрытий, кроме закрытия для BufferedOutputStream, и последующего закрытия самого сокета в блоке finally в виде ремня и скобок. Вы отключаете и закрываете все остальное перед выходным потоком, что предотвращает его сброс. Закрытие выходного потока очищает его и закрывает сокет. Это все, что вам нужно.

person user207421    schedule 04.12.2010

ОП здесь, не могу комментировать исходный пост.

  • Перезапуск серверного процесса не решает проблему. Сеть остается очень «зависающей» даже через несколько минут после полного выключения сервера.

  • Под «задержкой» я подразумеваю, что соединение становится чрезвычайно медленным как при восходящем, так и при нисходящем трафике. Попытки загрузить веб-сайты или загрузить их на мой FTP мучительно медленны, как будто я пользуюсь модемом 14,4k (я использую оптоволокно 15 Мбит/с). Интернет-тесты скорости даже не работают, когда он находится в этом состоянии - я получаю сообщение об ошибке, что файл не найден, когда веб-сайты в конечном итоге загружаются.

  • Все это мгновенно проясняется после перезагрузки, и только после перезагрузки.

  • Я изменил свой метод отключения, как предложил EJP, но проблема не устранена.

  • Сервер работает на установке Windows 7, последней версии Java/Java SDK. На сервере 16 ГБ оперативной памяти, хотя, возможно, я не распределяю ее должным образом, чтобы JVM могла полностью использовать ее. Блуждающих потоков или процессов не наблюдается. Я посмотрю, что скажет JVISUALVM. – jysend 13 минут назад

  • В JVISUALVM нет ничего необычного — куча 10 МБ, загрузка ЦП 50%, 3160 объектов (ожидается), запущено 27 активных потоков из 437. Сервер работает около 18 часов; загрузка главной страницы CNN занимает около минуты, и обычный тест скорости, который я использую (первый тест скорости поиска в Google), даже не загружает страницу. NETSTAT не показывает затяжных соединений. Запустил все современные антивирусы. В прошлом сервер работал 24/7 без каких-либо проблем - это начало происходить только тогда, когда я начал запускать на нем этот Java-сервер.

person jysend    schedule 08.12.2010