Search code examples
tcpgo

How to know TCP connection is closed in net package?


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?


Solution

  • 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 return io.EOF from zero byte reads