![Socat не закрывает TCP-соединение](https://rvso.com/image/1490203/Socat%20%D0%BD%D0%B5%20%D0%B7%D0%B0%D0%BA%D1%80%D1%8B%D0%B2%D0%B0%D0%B5%D1%82%20TCP-%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5.png)
Я использую 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 ([email protected]) 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({5}, {6}, {"/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, {2, AF=2 CLIENT_IP:PORT}, 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
Но почему это происходит при подключении, а не при отключении?
решение1
Когда вы отключаете клиента, у него нет возможности сообщить другой стороне, что он уходит. Единственный способ узнать, что пир ушел, — это попытаться отправить ему что-нибудь и заметить, что он не отвечает.
Если в вашем приложении требуется обнаружение мертвого пира, вам придется реализовать обнаружение мертвого пира. Вы можете сделать это, включив опцию keepalive
в socat
, но это все равно может занять несколько часов, чтобы обнаружить мертвого пира. Вы также можете сделать это, отправляя что-то периодически — отправка будет заблокирована, если пир мертв, вызывая обнаружение. Если другая сторона должна отправлять вам данные, вы можете прервать отправку, если вы не получили ожидаемые данные (возможно, с помощью socat
флага -T
).