Поведение тайм-аута неблокирующего сокета Java Linux

У меня есть неблокирующий сервер Java, который отслеживает все каналы сокетов в селекторе. Затем я устанавливаю 500 подключений к серверу и регулярно отправляю данные. Каждая часть данных, которую получает сервер, возвращается клиенту.

Проблема возникает, когда тест прекрасно работает в течение нескольких часов, а затем внезапно постепенно все сокеты, которыми управляет сервер, выдают исключение Connection timed out IOException при попытке чтения данных.

Я проверил, голодает ли клиентский поток (и не отправляет ли он данные), но я уступаю клиентскому потоку, который перебирает все сокеты и записывает данные. Трафик вроде бы постоянно течет исправно, но через какое-то время просто все замирает. Любые идеи, что может быть причиной такого поведения?

Я работаю на платформе Linux с последней итерацией Java 6. Мое приложение запускает два потока: один для сервера и один для всех клиентов. Заранее спасибо!

Дополнительно: проблема связана с Linux, а не с моим кодом. Когда я запускаю ту же самую настройку на компьютере с Windows (на том же оборудовании), время ожидания никогда не истекает, но через несколько часов они начинают происходить в Linux. Это должно быть какая-то настройка TCP в Linux, из-за которой это происходит. Спасибо за предложение.


person user126368    schedule 21.06.2009    source источник
comment
У вас есть код, чтобы показать нам?   -  person Chris Jester-Young    schedule 21.06.2009
comment
Также вывод netstat -a on клиента и сервера? Какие-нибудь сокеты в неудовлетворительном состоянии?   -  person John Kugelman    schedule 21.06.2009
comment
Не могли бы вы опубликовать вывод ex.printStackTrace() этого IOException?   -  person nos    schedule 14.07.2009
comment
Я думаю, что вам нужно опубликовать код и подробную трассировку стека IOException, как предложил nonelasd, чтобы решить эту проблему.   -  person Todd Stout    schedule 15.07.2009


Ответы (3)


Проблема связана с Linux, а не с моим кодом. Когда я запускаю ту же самую настройку на компьютере с Windows (на том же оборудовании), время ожидания никогда не истекает, но через несколько часов они начинают происходить в Linux. Это должно быть какая-то настройка TCP в Linux, из-за которой это происходит. Спасибо за предложение.

person user126368    schedule 26.06.2009
comment
Вы видели комментарии Криса и мои? Нам нужно больше информации, чтобы помочь. - person John Kugelman; 27.06.2009
comment
Я переместил эту информацию в вопрос - это, вероятно, не должно быть ответом - person Nick Fortescue; 13.07.2009

Параметр -doCloseWithReadPending в Java и JRE версий 1.5 или 5.0 позволяет одному потоку закрывать сокет, когда в том же сокете есть отложенное чтение из другого потока.

Когда close() вызывается для сокета, который имеет ожидающий вызов чтения из другого потока, close() по умолчанию блокирует сокет до тех пор, пока вызов чтения не завершится.

С опцией -doCloseWithReadPending вызов socket close() закрывает сокет, и в контексте потока с ожидающим чтением создается исключение SocketException с сообщением "Socket Closed".

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

person Amir Afghani    schedule 22.06.2009

Таким образом, как в случае, который работает (Windows с последней JVM), так и в случае, когда это не работает (Linux с последней JVM), и сервер, и клиент находятся на одной машине в одной и той же JVM?

Не могли бы вы пояснить, что означает выражение «внезапно постепенно»? Например, через несколько часов — и всегда одно и то же количество часов — затем в течение нескольких секунд все сокеты на стороне сервера выдают исключения?

Вы не упоминаете поток клиента, читающий возвращаемые данные. Возможно, он остановился, а вы не заметили. (Что делает клиентский поток, когда серверный поток сталкивается с 500 быстрыми исключениями? Попробуйте последовательно сделать несколько дампов стека, чтобы увидеть.)

person gojomo    schedule 03.07.2009
comment
Примерно через 4-5 часов клиентские сокеты Linux начинают отключаться по таймауту (хотя они все еще отправляют данные). Когда он запускается, между каждым клиентом происходит задержка около четверти секунды, когда он выключается. Когда я подключаю клиентов в начале, у меня есть задержка 250 мс между подключениями, поэтому кажется, что все они истекают после того, как были активны в течение одного и того же периода времени. Это очень странно. Это не происходит в Windows. - person user126368; 06.07.2009
comment
Проблема существует на клиентах, потому что сервер получает -1, что, насколько я знаю из документации, означает, что клиент чисто отключил сокет. Сервер живет своей жизнью. - person user126368; 06.07.2009
comment
Я бы не стал предполагать, что -1/EOF означает чистое отключение - просто поток чтения закончился по какой-то причине. В вашем первоначальном отчете говорилось, что сервер столкнулся с исключениями; теперь ты говоришь, что это не так? Пожалуйста, ответьте на другие вопросы от всех, если вы хотите решить эту проблему. (1) код; (2) вывод netstat; (3) Подтвердите, работают ли клиент и сервер в одной и той же JVM в обоих случаях; (4) Дампы стека (SIGQUIT/Ctrl-Break) во время работы и сразу после нее. Фактический стек ошибок также может помочь, и вы должны проверить, не возникает ли та же проблема с одним сокетом. - person gojomo; 06.07.2009
comment
нослада: Неправда; как SocketChannels, так и традиционные InputStreams возвращают -1 в конце данных, даже если ошибки нет. См. java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/ или java.sun.com/j2se/1.5.0/docs/api/java/io/ . - person gojomo; 15.07.2009
comment
Я думаю, что эти ссылки случайно сломались: вот, что я думаю, что они должны были быть: java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/ и java.sun.com/j2se /1.5.0/docs/api/java/io/ - person Stobor; 16.07.2009