#java #sockets #timeout
#java #сокеты #время ожидания
Вопрос:
У меня есть простое серверное клиентское приложение. Все работает, но на каком-то этапе требуется более 5 минут, чтобы получить ответ от сервера (что нормально, и это должно быть так). Проблема в том, что если это занимает более 5 минут, я продолжаю получать это исключение : java.net.SocketTimeoutException: Read timed out
.
Поэтому мне было интересно, есть ли какой-то тайм-аут сокета по умолчанию в Windows или на виртуальной машине Java, который я мог бы установить? Я не могу изменить клиентский код, поэтому setSoTimeout()
для меня это не вариант.
Использование Windows XP..
РЕДАКТИРОВАТЬ: как я теперь понимаю, соединение с сокетом не открывается на стороне клиента. Он передается с сервера. Итак, я декомпилировал весь файл jar сервера. Но все равно не могу найти ничего о тайм-ауте.
Комментарии:
1. Проверьте, настроен ли тайм-аут с помощью системных свойств.
2. @HannoBinder, можете ли вы объяснить, что вы подразумеваете под свойствами системы?
3. Я имею в виду что-то вроде sun.net.client.defaultReadTimeout или что-то еще, что может применяться к способу подключения вашего клиента.
4. Время ожидания сокета устанавливается клиентом. ‘Соединение с сокетом не открывается на стороне клиента. Его передача с сервера ‘ неверна.
Ответ №1:
Время ожидания сокета по умолчанию равно 0, что означает, что время ожидания никогда не истекает. Если оно действительно истекло через 5 минут, это означает, что оно было установлено в коде. Если исходный код недоступен и нет конфигурации, вы можете попытаться декомпилировать класс и искать setSoTimeout
вызовы.
Поскольку комментарии и тот факт, что поисковые запросы не нашли никаких вызовов setSoTimeout(), вы можете использовать другой подход. Просто дайте ему время ожидания и напишите небольшой скрипт, который повторит вызов в случае, если это произойдет. Если вы можете вызвать свой клиент из командной строки, вы можете проанализировать выходные данные, если они передаются в stderr.
Комментарии:
1. Я декомпилировал и искал
setSoTimeout
вызовы, но ничего не нашел. Значит, он должен быть установлен где-то в другом месте?2. @hs2d Я думаю, что он использует значение по умолчанию для поля int 0
Ответ №2:
Сохранение неиспользуемого TCP-соединения открытым в течение длительного времени без какого-либо трафика не так уж и тривиально. Многие брандмауэры / маршрутизаторы закрывают неиспользуемые порты после некоторого тайм-аута.
Одним из вариантов может быть реализация простого протокола keepalive для отправки фиктивных пакетов время от времени, но если вы не можете прикоснуться к клиентскому коду, это, вероятно, не вариант.
Редактировать: я не знаю ни одного способа переопределить setSoTimeout(), установленный в клиентском коде.
Комментарии:
1. @benez я не согласен. Если маршрутизатор считает соединение таким ценным ресурсом, что время его ожидания истекает, у вас нет никакого бизнеса, заставляющего его оставаться открытым. В любом случае вам все равно придется иметь дело с потерями соединения. Добавление пингов keepalive — это просто бессмысленная боль в шее на самом деле.
2. @EJP я еще не видел надлежащей реализации для обработки потерь соединения. бывают случаи, когда вы ожидаете обновлений в реальном времени, и вам нужно, чтобы две стороны были постоянно подключены, чтобы синхронизировать свои данные. потери соединения не просто обрабатываются простым повторным подключением. вы пропустите важное сообщение или получите его с опозданием. например, фондовые рынки всегда отправляют сердцебиения, а протокол irc требует, чтобы вы отвечали на ping с помощью pong. и да, вам приходится иметь дело с потерями соединения, но вы можете захотеть избежать их в некоторых программах.
3. @EJP добавление биений сердца может иметь решающее значение. Просто представьте следующий сценарий: после некоторого простоя на одном из компьютеров произошел сбой питания. При чистом отключении протокол TCP / IP уведомляет об этом другую сторону, но, напротив, когда на одном из компьютеров происходит сбой питания, тогда, конечно, никто не получает уведомления об этом. И это не будет обнаружено автоматически. В таких ситуациях, согласно другому компьютеру, соединение все еще установлено, и все кажется нормальным. Только когда клиент попытается что-то отправить, он обнаружит проблему.
Ответ №3:
Ответ, что 0 — это время ожидания по умолчанию, не совсем верно. Поскольку, например, клиент Axis2 имеет тайм-аут по умолчанию в 60 секунд, это будет зависеть от того, какую реализацию вы используете для выполнения вызова.
Можете ли вы предоставить более подробную информацию? Извините, что написал в разделе ответов, но у меня недостаточно репутации, чтобы делать комментарии 🙂
Комментарии:
1. Глядя на код здесь, я вижу только
java.io.InputStream
. Значит, соединение должно выполняться с сервера на клиент?2. ну, да, для Java значение по умолчанию бесконечно, но библиотека может это изменить. Может быть, это подсказка, hs2d, у вас есть какой-нибудь jar в комплекте? Или, может быть, вы можете использовать другой подход, просто дайте ему время ожидания и повторите попытку, если она завершится неудачей.
Ответ №4:
И вам нужно поддерживать соединение в рабочем состоянии? Почему бы вам не переосмыслить это, чтобы сделать его более асинхронным. Эта схема вообще не масштабируется. В какой-то момент все ваши доступные потоки могут долго ожидать ответа от сервера.
Комментарии:
1. Ему нужно поддерживать соединение, если он хочет читать из него. Не могу разобраться во всем этом.