Установка тайм-аута для операций с сокетами

86

Когда я создаю сокет:

Socket socket = new Socket(ipAddress, port);

Это вызывает исключение, что нормально, потому что IP-адрес недоступен. (Тестовые переменные где String ipAddress = "192.168.0.3"и int port = 300.)

Проблема в следующем: как мне установить тайм-аут для этого сокета?

Когда я создаю сокет, как мне сократить время до того, как я получу UnknownHostExceptionи заставлю сокет истечь время ожидания?

Дженнифер
источник
10
@adrianboimvaser: в этом случае вы должны пометить как дубликат и оставить комментарий, указывающий на дубликат, чтобы модератор мог закрыть его как таковой (вы оставили этот комментарий год назад - возможно, вы уже знаете это). Я бы проголосовал за это сейчас, но понятия не имею, где находится дубликат!
Том Андерсон
1
Чтобы продолжить тенденцию к тому, чтобы отвечать на годы с опозданием, @EJP, название этого вопроса гораздо менее двусмысленно, чем дубликат, который вы предложили
Исаак
@Isaac И на самом деле это не дубликат, комментарий отклонен.
Marquis of Lorne
(Примечание: я изменил название, чтобы сделать его менее двусмысленным.)
Стивен С.

Ответы:

165

Вместо этого используйте Socket()конструктор и connect(SocketAddress endpoint, int timeout)метод .

В вашем случае это будет выглядеть примерно так:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

Цитата из документации

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

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

Параметры:

endpoint- SocketAddress
timeout- значение тайм-аута в миллисекундах.

Броски:

IOException- если во время соединения возникает ошибка
SocketTimeoutException- если таймаут истекает до подключения
IllegalBlockingModeException- если у этого сокета есть связанный канал, и канал находится в неблокирующем режиме
IllegalArgumentException- если конечная точка равна нулю или является подклассом SocketAddress, не поддерживаемым этим сокетом

Начиная с: 1.4

aioobe
источник
4
Это может уменьшить тайм-аут для ConnectException (но не увеличить его) и не влияет на тайм-аут для UnknownHostException, который OP утверждает, что он получает (хотя я в это не верю). Также обратите внимание, что Javadoc неверно утверждает, что значение по умолчанию - бесконечность. Это не так. По умолчанию платформа имеет тайм-аут около минуты, и его нельзя увеличить.
Маркиз Лорн
3
Даже через 4 года это было полезно, это должен быть принятый ответ.
Sharp Edge
4
Прошло 5 лет, и это лучший ответ, который я нашел в Интернете .. Спасибо
MBH
1
Также важно вызывать socket.setSoTimeout(timeoutMillis)тайм-ауты при блокировании операций ввода-вывода.
Gray
43

Вы не устанавливаете тайм-аут для сокета, вы устанавливаете тайм-аут для операций, которые вы выполняете на этом сокете.

Например socket.connect(otherAddress, timeout)

Или socket.setSoTimeout(timeout)для установки тайм-аута read()операций.

См .: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html

Payne
источник
Ну в данном случае это тоже операция, подключение. Я не могу найти места, где говорится, что этот ctor использует бесконечный тайм-аут, хотя, похоже, это так.
Sandos
3
@sandos Это ясно указано в документации Javadoc для connect (). Однако это тоже неверно. Таймаут по умолчанию - это тайм-аут платформы, около минуты, а не бесконечности, и он может быть уменьшен только этим методом connect (), но не увеличен.
Маркиз Лорн
обратите внимание, socket.setSoTimeoutдолжно вызываться ПОСЛЕ connect, иначе это не будет иметь никакого эффекта и время чтения никогда не истечет. это одна плохо задокументированная ошибка.
pstanton 01
19

Вы можете использовать следующее решение:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

Надеюсь, это поможет!

риф
источник
1
Если, как он утверждает, он получает исключение UnknownHostException, это произойдет в первой строке, где не действует измененный тайм-аут.
Маркиз Лорн
Однако первая строка не вызывает никаких исключений. Из документации: «Будет предпринята попытка преобразовать имя хоста в InetAddress. Если эта попытка не удалась, адрес будет помечен как неразрешенный»
ady
В этом случае он будет разрешен connect()методом, но не по таймауту.
Marquis of Lorne
8

Вы не можете контролировать тайм-аут из-за UnknownHostException. Это тайминги DNS. Вы можете контролировать время ожидания подключения только при наличии допустимого хоста. Ни один из предыдущих ответов не касается этого вопроса правильно.

Но мне трудно поверить, что вы действительно получаете, UnknownHostExceptionкогда указываете IP-адрес, а не имя хоста.

ИЗМЕНИТЬ Чтобы контролировать тайм-ауты DNS Java, см. Этот ответ .

Маркиз Лорн
источник