Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know TCP connection is closed in net package?

Tags:

tcp

go

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?

like image 682
liuyanghejerry Avatar asked Oct 05 '12 07:10

liuyanghejerry


People also ask

How do I know if my TCP connection is closed?

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.

What happens when a TCP connection is closed?

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.

How long do TCP connections stay open?

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.

When TCP connection is open?

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.


2 Answers

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

like image 166
VonC Avatar answered Sep 17 '22 19:09

VonC


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"

like image 36
minikomi Avatar answered Sep 19 '22 19:09

minikomi