如何知道远程tcp设备是否已关闭

时间:2017-02-28 11:52:53

标签: python sockets go tcp

在我的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 {
        //remote connection close handle
        fmt.Println("connection got reset by peer")
        panic(err)
    }
}

为了模拟另一端,我在另一台计算机上运行一个python脚本,它打开一个套接字并将一些随机数据发送到代码行正在侦听的套接字上。现在我的问题是,当我按ctrl + C杀死这个python代码时,远程连接关闭事件被上面的代码很好地识别,我有机会处理它。

但是,如果我只是关闭远程计算机(运行python脚本的地方),我的代码根本不会得到通知。

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

有人可以在这种情况下帮助我,当托管套接字本身的远程计算机关闭时,我如何收到通知?如何在GO代码中远程获取触发器?

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

2 个答案:

答案 0 :(得分:2)

无法确定断电的主机与已断开的连接之间的区别,因此您可以采用相同的方式对待它们。

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

您也可以使用TCP Keepalive为您执行此操作,使用TCPConn.SetKeepAlive启用它,TCPConn.SetKeepAlivePeriod设置keepalive数据包之间的间隔。实际关闭连接所需的时间取决于系统。

您还应该在拨号时设置超时,因为无法保证连接到主机不会返回ICMP Host Unreachable响应。您可以使用DialTimeoutnet.Dialer设置Timeout参数,或Dialer.DialContext

只需阅读stdlib文档即可为您提供大量信息:https://golang.org/pkg/net/

答案 1 :(得分:0)

您需要添加某种心跳消息。然后,查看GO文档,您可以使用DialTimeout而不是Dial,每次收到心跳消息或其他任何可以重置超时的消息。

另一种选择是使用TCP keepalive。您可以使用setsockopt在Python中执行哪些操作,我无法真正帮助您使用GO,但此链接似乎是如何使用它启用keepalive的良好说明: http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html