Java TLS Socket Write не может обнаружить сброс подключения - PullRequest
0 голосов
/ 08 октября 2018

Я борюсь со своевременным обнаружением сброса соединения на сокете Java TLS.

Я имею дело с клиентом syslog-over-TLS, который теряет сообщения.Клиент системного журнала отправляет сообщения по мере их поступления и для этой цели сохраняет один сокет TLS открытым, если не возникает ошибка, в этом случае он сбрасывает сокет и открывает новое соединение.

Для исследования этой проблемы я отправляю то же самоетип и размер сообщения снова и снова.

Происходит следующее:

  1. Запустить клиент
  2. 1-е сообщение приходит - новый сокет открыт и сообщение успешно передано в удаленный системный журнал (код ниже)
  3. Не используется в течение 15 минут
  4. 2-е сообщение приходит - существующий сокет используется для отправки сообщения;сброс соединения tcp получен, но исключение не выдается;сообщение утеряно
  5. 3-е сообщение приходит вскоре после этого - запись в сокет сразу же завершается с исключением: сброс соединения;клиент открывает новый сокет и успешно отправляет сообщение

Код для отправки сообщений (тоже?) прост:

OutputStream out = socket.getOutputStream();
out.write(syslogFrame);
out.write(msgBytes);
out.flush();

Почему я не получаю исключение прямо на второмсамое позднее сообщение для второй операции записи в приведенном выше коде?И как я могу убедиться в этом?

Сообщение значительно больше, чем MTU, и график ввода / вывода довольно ясно показывает, что 2-е сообщение даже не проходит по проводам:

enter image description here

Полная трассировка: соединение установлено в пакете № 2.Пакеты до # 27 являются передачей первого сообщения.# 28, # 29, # 30 - начало 2-го сообщения, на которое ответил сброс соединения.На данный момент в коде Java нет исключений.Операция записи в сокет возвращается без ошибки, но сообщение теряется.Операция записи для 3-го сообщения теперь получает исключение «Сброс подключения», которое запускает код клиента для восстановления соединения в пакетах № 33 и далее, а 3-е сообщение затем передается по проводам.

enter image description here

Моими операционными системами, на которых работает клиент, является Linux Mint 18.3 (Kernel 4.10.0-38-generic) с Oracle JDK 1.8.0_172 и 10.0.2;CentOS Linux 7.5.1804 (ядро 3.10.0-693.21.1.el7.x86_64) и Oracle JDK 1.8.0_172.

1 Ответ

0 голосов
/ 04 декабря 2018

Проблема на самом деле присуща всем симплексным протоколам, реализованным в TCP.И это несколько усугубляется тем фактом, что записи в Java имеют тенденцию возвращаться до того, как какие-либо байты будут фактически вытеснены из стека TCP.Даже на flush().Так что сигнализация ненадежна по замыслу.

Единственный надежный способ определения работоспособности соединения через сокет - чтение с него.Но с симплексным протоколом читать нечего.Вот почему rsyslog реализует протокол RELP , который добавляет обратный канал, по которому отправляются сообщения ACK / NAK уровня приложения.

...