如何知道远程TCP设备是否下电

In my GO code, I am establishing a TCP connection as below:

conn, err1 := net.Dial("tcp", <remote_address>)
if err1 == nil {
    buf := make([]byte, 256)
    text, err := conn.Read(buf[:])
    if err == io.EOF {
        //remote connection close handle
        fmt.Println("connection got reset by peer")
        panic(err)
    }
}

To simulate the other end, I am running a python script on a different computer, which opens a socket and sends some random data to the socket above lines of codes are listening to. Now my problem is, when I am killing this python code by pressing ctrl+C, the remote connection closed event is recognised finely by above code and I get a chance to handle that.

However, if I simply turn off the remote computer (where the python script is running) my code doesn't get notified at all.

In my case, the connection should always be opened and should be able to send the data randomly, and only if the remote machine gets powered off, my GO code should get notified.

Can someone help me in this scenario, how would I get notification when the remote machine hosting the socket itself gets powered off? How would I get the trigger remotely in my GO code?

PS - This seems to be a pretty common problem in real time, though not in the testing environment.

You need to add some kind of heartbeat message. Then, looking at GO documentation, you can use DialTimeout instead of Dial, each time you receive the heartbeat message or any other you can reset the timeout.

Another alternative is to use TCP keepalive. Which you can do in Python by using setsockopt, I can't really help you with GO but this link seems like a good description of how to enable keepalive with it: http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html

There is no way to determine the difference between a host that is powered off and a connection that has been broken, so you treat them the same way.

You can send a heartbeat message on your own, and close the connection when you reach some timeout period between heartbeat packets. The timeout can either be set manually by timing the packets, or you can use SetReadDeadline before each read to terminate the connection immediately when the deadline is reached.

You can also use TCP Keepalive to do this for you, using TCPConn.SetKeepAlive to enable it and TCPConn.SetKeepAlivePeriod to set the interval between keepalive packets. The time it takes to actually close the connection will be system dependent.

You should also set a timeout when dialing, since connecting to a down host isn't guaranteed to return an ICMP Host Unreachable response. You can use DialTimeout, a net.Dialer with the Timeout parameter set, or Dialer.DialContext.

Simply reading through the stdlib documentation should provide you with plenty of information: https://golang.org/pkg/net/