I'm implementing a small TCP server. How do I know if one of my clients closed? Should I just try to read or write and check if err
is nil?
Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17. xxx. xxx 5000) to run the telnet command in Command Prompt and test the TCP port status. If the port is open, only a cursor will show.
After completing the data transfer, the TCP client calls close to terminate the connection and a FIN segment is sent to the TCP server. Server-side TCP responds by sending an ACK which is received by the client-side TCP.
There is no limit in the TCP connection itself. Client and server could in theory stay connected for years without exchanging any data and without any packet flow. Problems are usually caused by middleboxes like NAT router or firewalls which keep a state and expire the state after some inactivity.
TCP Open Connection is a synchronous activity that opens a connection to a TCP server. After establishing the connection, the activity places a handle to the open connection in the connection output element.
That thread "Best way to reliably detect that a TCP connection is closed", using net.Conn
for 'c
' (also seen in utils/ping.go
or locale-backend/server.go
or many other instances):
one := make([]byte, 1) c.SetReadDeadline(time.Now()) if _, err := c.Read(one); err == io.EOF { l.Printf(logger.LevelDebug, "%s detected closed LAN connection", id) c.Close() c = nil } else { var zero time.Time c.SetReadDeadline(time.Now().Add(10 * time.Millisecond)) }
For detecting a timeout, it suggests:
if neterr, ok := err.(net.Error); ok && neterr.Timeout() { ...
Update 2019: tuxedo25 mentions in the comments:
In go 1.7+, zero byte reads return immediately and will never return an error.
You must read at least one byte.
See commit 5bcdd63 and go issue 15735
net
: don't returnio.EOF
from zero byte reads
Just try to read from it, and it will throw an error if it's closed. Handle gracefully if you wish!
For risk of giving away too much:
func Read(c *net.Conn, buffer []byte) bool { bytesRead, err := c.Read(buffer) if err != nil { c.Close() log.Println(err) return false } log.Println("Read ", bytesRead, " bytes") return true }
Here is a nice introduction to using the net package to make a small TCP "chat server":
"Golang Away: TCP Chat Server"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With