This should be very simple, and probably is for people who know what they are doing, which I clearly don't.
I am using a Raspberry Pi 3 running Ubuntu Server 16.04 to receive an ASCII stream on a RS-232 <-> USB converter, and send it to multiple clients over a LAN using raw TCP. (each client connects to a separate TCP port on the server)
My script uses socat to read the data from /dev/ttyUSB0 and broadcast it via UDP on the loopback device. (This was the only way I could find that would mean that 1) the data was continually read from /dev/ttyUSB0 even if no further process was wanting it, and 2) multiple processes could read the same stream)
socat -d -U udp-sendto:127.255.255.255:29000,broadcast file:/dev/ttyUSB0,nonblock
Then multiple instances of socat listen for TCP connections, then read from the UDP broadcast and send it on
socat -u -d udp-recv:29000,reuseaddr,rcvbuf=2048 tcp-l:$port,keepalive,keepcnt=5,keepidle=10,keepintvl=2
This all works fine, when clients close their connection, my scripts sees that the socat process has stopped and starts it again ready for the next connection. The problem is with clients that do not close their connections properly. This is going to be used in an environment where clients WILL have their network cables unplugged or be hard-powered-down, and the server needs to make the ports available again as quick as possible.
For testing, I am using a simple nc -vv server.ip serverport
on a Ubuntu laptop.
As it stands, if a client is unplugged, the server keeps the connection open for around 1 hour. (netstat shows the connection as ESTABLISHED)
If I add the -T 20
to the TCP socats, is will bin the dead connection after 1 minute. (The port then stays in FIN_WAIT1 for a minute, but this is bearable)
BUT, the -T option also causes the connection to be closed when the client is still connected but there is no serial data coming in! The keepalives are being sent (when the script and thus the socats) is run as root (I have checked with Wireshark on the laptop), but I assume that as they are only on the TCP link between server and client, socat sees the link between its input (UDP) and output (TCP) as dead, and closes.
All connections are unidirectional. Serial into server, TCP stream from server to clients.
What I want is:
Keep the TCP connection to a client open indefinitely, regardless of whether any data is being sent.
Close the connection within 30 secs if there is no ACK response from the client (either from a data packet or keepalive).
Re-open ports for future connections within 1 minute.
Sorry if this is all over the place, but I hope I have given all the required information.