Сокат не закрывает TCP-соединение

2185
Lost in OWL

Я использую socat 1.7.3.1-r0и запускаю следующую команду на alpine 3.3сервере Linux:

socat -d -d -d PTY,link=/dev/ttyFOOBAR,echo=0,raw,unlink-close=0 TCP-LISTEN:7000,forever,reuseaddr 

Socatбудет прослушивать клиентов и создавать двунаправленную связь, передавая данные из виртуального последовательного порта /dev/ttyFOOBARклиенту и обратно через TCP. Как только клиент отключается, socatдолжен выйти.

Когда такое соединение установлено, socat регистрирует следующее:

I socat by Gerhard Rieger - see www.dest-unreach.org I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/) I This product includes software written by Tim Hudson (tjh@cryptsoft.com) I setting option "symbolic-link" to "/dev/ttyFOOBAR" I setting option "echo" to 0 I setting option "raw" I setting option "unlink-close" to 0 I openpty(,, {"/dev/pts/3"},,) -> 0 N PTY is /dev/pts/3 I setting option "forever" to 1 I setting option "so-reuseaddr" to 1 I socket(2, 1, 6) -> 7 I starting accept loop N listening on AF=2 0.0.0.0:7000 I accept(7,, 16) -> 8 N accepting connection from AF=2 CLIENT_IP:PORT on AF=2 172.20.0.2:7000 I permitting connection from AF=2 CLIENT_IP:PORT I close(7) I resolved and opened all sock addresses N starting data transfer loop with FDs [5,5] and [8,8] 

ss Команда на сервере печатает:

Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port  tcp ESTAB 0 0 172.20.0.2:7000 CLIENT_IP:PORT 

Проблема в том, что, когда я отключаю клиента (отключая его), соединение tcp все еще устанавливается, и от socat не поступает дополнительная регистрация. ssвсе еще показывает соединение как ESTAB. Есть идеи почему? При повторном подключении клиента в журналах появляется следующее:

W read(8, 0x7fa8f48c4020, 8192): Connection reset by peer N socket 2 to socket 1 is in error N socket 2 (fd 8) is at EOF I poll timed out (no data within 0.500000 seconds) I close(5) I shutdown(8, 2) I shutdown(8, 2): Socket not connected N exiting with status 0 

Но почему это происходит при подключении, а не отключении?

0

1 ответ на вопрос

1
David Schwartz

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

Если в вашем приложении требуется, чтобы обнаруживался мертвый одноранговый узел, вам необходимо реализовать обнаружение мертвого однорангового узла. Вы можете сделать это, включив эту keepaliveопцию socat, но это может занять несколько часов, чтобы обнаружить мертвый узел. Вы также можете сделать это, отправляя что-то периодически - отправка будет иметь тайм-аут, если узел мертв, вызывая обнаружение. Если другая сторона должна отправлять вам данные, вы можете прервать ее, если вы не получили ожидаемые данные (возможно, с флагом socat's' -T).