Как обнаружить флаг FIN - tcp в приложении Java? - PullRequest
2 голосов
/ 26 марта 2012

У меня длительное TCP-соединение между двумя компьютерами (второе не под моим контролем). Второй компьютер может отправлять флаг FIN в любой момент, и первый должен закрыть соединение (отправить флаг FIN обратно на второй компьютер).

Как я могу узнать, что второй компьютер отправляет флаг FIN и когда мне нужно вызвать метод socket.close () моего Java-приложения?

Ответы [ 3 ]

2 голосов
/ 26 марта 2012

Обычно вы должны прочитать соединение, и когда оно возвращает -1 для EOF или соответствующего исключения IOException, вы можете закрыть соединение.Примечание: SocketTimeoutException не означает, что соединение закрыто.

пример.

boolean ok = false;
try {
  int b = in.read();
  ok = b >= 0;
  if (!ok)
     throw new EOFException();
} finally {
  if (!ok)
     in.close();
}
1 голос
/ 26 марта 2012

Обнаружение мягкого соединения вблизи другой стороны (когда им удается отправить флаги FIN / RST) возможно только частично со старой библиотекой ввода / вывода Java. О нарушенном соединении вы узнаете только через тайм-аут, поэтому он может быть далек от немедленного. Ваши темы могут долго зависать, прежде чем они поймут, что вечеринка на другом конце давно прошла.

Чтобы справиться с этим лучше, вам нужно использовать nio. Там такая ситуация будет распознаваться Selector, говоря, что есть данные, готовые для чтения, но затем считанные по каналу, возвращающие меньше нуля. Это позволит вам почти сразу же узнать о перезагрузке программных соединений.

С другой стороны, завершение жесткого соединения (например, кто-то обрывает провод или отключение сети) может быть обнаружено только через тайм-ауты, независимо от того, какие библиотеки вы используете, так как это свойство самого протокола TCP.

0 голосов
/ 03 сентября 2018

Как объяснено выше, свойства Socket (isClosed, isConnected и т. Д.) Бесполезны.Правильным решением было бы установить разумный SO_TIMEOUT и прочитать из сокета:

  • В случае закрытого сокета операция чтения вернется с «-1»
  • В случае чтениятайм-аут, операция чтения будет возвращена с исключением тайм-аута чтения

(код Scala)

val socket = new Socket("localhost", 8888)
socket.setSoTimeout(10000) /* Set reasonable read timeout */

try {
    val res = socket.getInputStream().read()

    if (res < 0) 
      ... /* Socket closed */
    else
      ... /* Socket read succeeded */

} catch {
    case _: SocketTimeoutException => ... /* Socket not closed */
    case _ => ... /* Merde */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...