Встановлення часу очікування для операцій сокета


86

Коли я створюю сокет:

Socket socket = new Socket(ipAddress, port);

Він видає виняток, що нормально, оскільки IP-адреса недоступна. (Тестові змінні де String ipAddress = "192.168.0.3"і int port = 300.)

Проблема полягає в тому, як мені встановити час очікування для цього сокета?

Коли я створюю сокет, як зменшити час, перш ніж отримати UnknownHostExceptionта отримати тайм-аут сокета?


10
@adrianboimvaser: У такому випадку ви повинні позначити як дублікат і залишити коментар, вказуючи на дублікат, щоб модератор міг його закрити як такий (ви залишили цей коментар рік тому - можливо, ви вже це знаєте). Я віддав би свій голос за це зараз, але я не уявляю, де дублікат!
Том Андерсон,

1
Щоб продовжити тенденцію відповідати на роки пізніше, @EJP заголовок цього запитання набагато менш неоднозначний, ніж дублікат, який ви запропонували
Ісаак

@Isaac А насправді це зовсім не дублікат, коментар відкликаний.
Маркіз Лорнський,

(Примітка: Я змінив цю назву, щоб вона була менш двозначною.)
Стівен С

Відповіді:


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


4
Це може зменшити час очікування для ConnectException (але не збільшити його), і це не впливає на час очікування для UnknownHostException, який ОП стверджує, що він отримує (хоча я не вірю в це). Також зауважте, що Javadoc неправильно стверджує, що за замовчуванням нескінченність. Це не так. За замовчуванням час очікування платформи становить близько хвилини, і це не можна збільшити.
Маркіз Лорнський

3
Навіть через 4 роки це було корисно, це має бути прийнятою відповіддю.
Sharp Edge

4
Зараз це через 5 років, і це найкраща відповідь, яку я знайшов в Інтернеті .. Дякую
MBH

1
Також важливо зателефонувати socket.setSoTimeout(timeoutMillis)за час очікування під час блокування операцій вводу-виводу.
Grey

43

Ви не встановлюєте час очікування для сокета, ви встановлюєте час очікування для операцій, які ви виконуєте в цьому сокеті.

Наприклад socket.connect(otherAddress, timeout)

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

Див .: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html


Ну, в цьому випадку це також операція, підключення. Я не можу знайти жодного місця, де говориться, що цей ктор використовує нескінченний тайм-аут, хоча це, здається, так.
sandos

3
@sandos Це чітко зазначено в Javadoc для connect (). Однак це також неправильно. Типовим тайм-аутом є тайм-аут платформи, приблизно хвилину, а не нескінченність, і його можна зменшити лише цим методом connect (), а не збільшити.
Маркіз Лорнський,

Примітка, його socket.setSoTimeoutпотрібно викликати ПІСЛЯ connect, інакше це не матиме ефекту, і читання ніколи не закінчиться це одна погано задокументована проблема.
пстантон

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()методом, але не під контролем тайм-ауту.
Маркіз

8

Ви не можете контролювати час очікування через UnknownHostException . Це терміни DNS. Ви можете контролювати лише час очікування підключення за дійсним хостом. Жодна з попередніх відповідей не стосується цього питання правильно.

Але мені важко повірити, що ти справді отримуєш UnknownHostException коли ви вказуєте IP-адресу, а не ім'я хосту.

EDIT Щоб контролювати час очікування DNS Java, див. Цю відповідь .


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.