Знаете ли вы, как установить тайм-аут на Socket в Java? В чем их отличие? Просто подумайте о сцене по телефону с вашей девушкой. Если вы действительно не можете об этом думать, давайте посмотрим, что происходит.
Как установить
Существуют в основном следующие два способа
Способ 1:
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host,port),10000);
Способ 2:
Socket socket = new Socket("127.0.0.1",8080);
socket.setSoTimeout(10000);
Так что же означают тайм-ауты, установленные этими двумя способами? какие отличия есть?
практическое тестирование
1-й способ
Давайте рассмотрим первый способ, проверим его: в основном методе мы создаем Socket подключение к ip: 29.212.19.201, порт: 2132
public static void main(String[] args) {
Socket socket = new Socket();
SocketAddress endpoint = new InetSocketAddress("29.212.19.201", 2132);
long timeMillis = System.currentTimeMillis();
try {
socket.connect(endpoint, 10000);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()-timeMillis);
System.out.println("end");
}
При выполнении этого кода в консоль не выводится информация до 10 секунд, а через 10 секунд печатается следующая информация:
10002
java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.wakling.cn.SocketSever.main(SocketSever.java:33)
end
Видно, что когда мы пытались подключиться к 29.212.19.201:2132, мы не подключались в течение 10 секунд, поэтому мы сообщилиjava.net.SocketTimeoutException: connect timed out
Время соединения истеклоисключение.
Объясните, что указанный выше IP-адрес является неизвестным IP-адресом, то есть IP-адрес локальной машины не может получить доступ к указанному выше IP-адресу в текущей сетевой среде, поэтому наш сокет будет пытаться подключиться к этому IP-адресу, пока не истечет время ожидания. Если приведенный выше IP-адрес является известным IP-адресом, например, локальный 127.0.0.1 плюс неизвестный порт, то подключение к сокету немедленно сообщит об ошибке.
Кроме того, без установки времени ожидания соединения значение Socket по умолчанию составляет около 21 с (проверено 3 раза, это 21020 миллисекунд).Время соединения истекло. Ниже приведен код без установки времени ожидания соединения:
Socket socket = new Socket("29.212.19.201", 2132);
2-й способ
Тогда давайте посмотрим на второй способ, На данный момент нам нужно написать набор Socket сервер + клиент локально, чтобы смоделировать этот сценарий.
Мы позволяем клиенту установитьsetSoTimeout
Это 10 сек. После того, как сервер получит информацию о запросе клиента, сервер спит в течение 10 сек перед обработкой запроса клиента, а затем возвращает ответ.
Давайте посмотрим на эффект, код клавиши выглядит следующим образом:
//服务端
System.out.println("进入休眠,10s后醒来");
Thread.sleep(10000);//休眠10秒
System.out.println("休眠结束");
//返回响应
OutputStream outputStream = socket.getOutputStream();// 获取一个输出流,向服务端发送信息
PrintWriter printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
printWriter.print("你好,服务端已接收到您的信息");
printWriter.flush();
//客户端
Socket socket = new Socket("127.0.0.1",2132);
socket.setSoTimeout(10000);//超时时间,10秒
После запуска дождитесь вывода клиента.Через 10 с информация о выводе консоли клиента выглядит следующим образом:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.wakling.cn.SocketClient.main(SocketClient.java:36)
10002
end
Здесь клиент бросает через 10 секундjava.net.SocketTimeoutException: Read timed out
тайм-аут чтенияисключение. Просмотр консольной информации серверной стороны является нормальным выводом.Даже если клиентская сторона сообщила о тайм-ауте, серверная сторона продолжает отключаться, но клиентская сторона не получила сообщение, отправленное самой себе серверной стороной через 10 секунд.
Кроме того, тест показал, что сервер находится в спящем режиме в течение длительного времени, например, 500 с. Когда клиент не устанавливает setSoTimeout, клиент по умолчанию использует тайм-аут 120 с. Официальное объяснение метода setSoTimeout следующее: я не знаю, действительно ли установка таймаута на 0 является бесконечным таймаутом, если вам интересно, можете попробовать.
setSoTimeout
public void setSoTimeout(int timeout)
бросает SocketException включает/отключает SO_TIMEOUT с указанным значением времени ожидания в миллисекундах.Когда для этой опции установлено ненулевое значение тайм-аута, вызов read() для InputStream, связанного с этим сокетом, будет блокироваться только на этот период времени.
Если значение тайм-аута превышено, будет выдано исключение java.net.SocketTimeoutException, хотя сокет все еще действителен. Опция должна быть включена перед входом в операцию блокировки, чтобы она вступила в силу.
Значение тайм-аута должно быть числом > 0.Значение тайм-аута, равное 0, интерпретируется как бесконечное значение тайм-аута..
Параметры: timeout - указанное значение таймаута в миллисекундах.
Выдает: SocketException — если есть ошибка базового протокола, например ошибка TCP.
Начиная с: JDK 1.1
См. также: getSoTimeout()
разница и смысл
Давайте поговорим о разнице и значении этих двух вещей.
Способ 1 — клиент и сервервремя соединения вышло, то есть если соединение не может быть установлено в течение 10 секунд, сообщитjava.net.SocketTimeoutException: connect timed out
Исключение времени ожидания соединения. В настоящее время соединение между ними не установлено, не говоря уже о том, что сервер получает сообщение от клиента.
Способ 2 - установитьВремя блокировки метода inputStream.read(), то есть время ожидания клиентом ответа сервера после выполнения запроса.java.net.SocketTimeoutException: Read timed out
аномальный. В это время соединение между ними устанавливается нормально, и сервер получает запрос клиента.
Разумная установка периода тайм-аута имеет большое значение для увеличения производительности программы и повышения надежности программы.
Фокус двух способов контроля тайм-аута различен.Так же, как девушка, звонящая вам, у нее небольшой характер. Если она относится к вам по способу 1, то есть бросает трубку, если вы не отвечаете на звонок в течение 10 секунд после совершения исходящего звонка, а если она использует способ 2, то есть после соединения звонка, если вы заняты, она будет ждать вас 10 секунд, если вы не будете говорить в течение 10 секунд, вы повесите трубку, через 10 секунд она не сможет услышать, говорите вы или нет, и вам будет грустно .
【КОНЕЦ】
Изображение на обложке взято из Интернета, а контакт с нарушением удален.