如何判断远程TCP设备是否已关闭电源

huangapple go评论92阅读模式
英文:

How to know if the remote tcp device is powered off

问题

在我的GO代码中,我正在建立一个TCP连接,代码如下:

conn, err1 := net.Dial("tcp", <remote_address>)
if err1 == nil {
    buf := make([]byte, 256)
    text, err := conn.Read(buf[:])
    if err == io.EOF {
        //处理远程连接关闭
        fmt.Println("连接被对方重置")
        panic(err)
    }
}

为了模拟另一端,我在另一台计算机上运行一个Python脚本,该脚本打开一个套接字并向上述代码监听的套接字发送一些随机数据。现在我的问题是,当我按下Ctrl+C来终止这个Python代码时,上述代码能够很好地识别到远程连接关闭事件,并且我有机会处理它。

然而,如果我只是关闭运行Python脚本的远程计算机,我的代码根本不会收到通知。

在我的情况下,连接应该始终保持打开状态,并且应该能够随机发送数据,只有当远程计算机关闭电源时,我的GO代码才应该收到通知。

有人可以帮助我解决这个问题吗?在远程计算机上关闭套接字时,我该如何在我的GO代码中远程触发通知?

PS - 这似乎是一个在实时环境中非常常见的问题,尽管在测试环境中不常见。

英文:

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

conn, err1 := net.Dial(&quot;tcp&quot;, &lt;remote_address&gt;)
if err1 == nil {
    buf := make([]byte, 256)
    text, err := conn.Read(buf[:])
    if err == io.EOF {
        //remote connection close handle
        fmt.Println(&quot;connection got reset by peer&quot;)
        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.

答案1

得分: 2

无法确定主机已关闭和连接已断开之间的区别,因此您可以将它们视为相同的处理方式。

您可以自己发送心跳消息,并在心跳数据包之间达到某个超时时间时关闭连接。超时时间可以通过计时数据包来手动设置,或者您可以在每次读取之前使用SetReadDeadline在截止日期到达时立即终止连接。

您还可以使用TCP Keepalive来完成此操作,使用TCPConn.SetKeepAlive启用它,并使用TCPConn.SetKeepAlivePeriod设置保持活动数据包之间的间隔。实际关闭连接所需的时间将取决于系统。

拨号时还应设置超时时间,因为连接到关闭的主机不能保证返回ICMP主机不可达响应。您可以使用DialTimeout,设置了Timeout参数的net.Dialer,或者Dialer.DialContext

简单地阅读stdlib文档应该会为您提供大量信息:https://golang.org/pkg/net/

英文:

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/

答案2

得分: 0

你需要添加某种心跳消息。然后,根据GO文档,你可以使用DialTimeout而不是Dial,每次收到心跳消息或其他消息时,可以重置超时时间。

另一种选择是使用TCP keepalive。在Python中,你可以使用setsockopt来实现,但我无法帮助你使用GO,不过这个链接似乎是一个很好的描述如何在GO中启用keepalive的资源:http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html

英文:

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

huangapple
  • 本文由 发表于 2017年2月28日 19:52:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/42508074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定