Настройка времени ожидания сокета

Java
Настройка времени ожидания сокета

Знаете ли вы, как установить тайм-аут на 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 секунд она не сможет услышать, говорите вы или нет, и вам будет грустно .

【КОНЕЦ】

Изображение на обложке взято из Интернета, а контакт с нарушением удален.