检测tcp断开连接的正确方法?手动keepalive空闲,并且没有工作SetWriteDeadLine

时间:2015-08-26 23:02:46

标签: sockets networking tcp go

我遇到TCP连接问题。

我有一个写入的服务器,在某些端口上监听tcp连接。 我的客户端用Java编写的Android版本。 客户端与服务器建立连接,然后在没有任何法律的情况下交换一些数据。

当Android更改网络类型时,例如从移动网络更改为wifi。连接已断开,但服务器不知道此问题,并认为客户端已准备好接收一些数据。

我需要尽快在我的服务器上检测到这个问题。理想情况下立即

我首先使用的是SetKeepAlive(true)SetKeepAlivePeriod(10 * time.Second)。它起作用了,但并不是我需要的那么快。因为去SetKeepAlivePeriod,将 tcp keepalive time(idle) tcp keepalive interval 设置为相同。例如,在linux tcp keepalive retry = 8 中,在(10 + 8 * 10)= 90秒= 1分30秒后检测到连接问题。这是非常慢的:(。如何设置空闲和间隔手动?我看这个lib https://github.com/felixge/tcpkeepalive,但我不相信这个lib,因为,在这个lib套接字fd复制没有明确。

我可以设置SetKeepAlivePeriod(1 * time.Second),但有关性能的最新消息?在我的情况下,连接可能是负载很重或空闲。

然后,我想到了SetWriteDeadline。这对我来说非常有用,因为我不知道我什么时候收到来自客户的消息,但我知道我何时向客户发送消息。但是,当我使用SetWriteDeadline时,无法正常工作。 例如

var request *http.Request

conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
err := request.Write(conn)
if err != nil {
    if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
        log.Println("Connection WriteDeadline timeout")
    }
    conn.Close();
} else {
    conn.SetWriteDeadline(time.Time{})
}

在客户端断开连接后,我将一些数据写入连接,方法写入返回nil没有错误。好像数据已经发送并且服务器成功接受来自客户端的ACK,但是如何?

更新28.10.2015 22:35

我决定尝试这个https://github.com/felixge/tcpkeepalive库。然而它完全适用于我的问题:)。

ka, _ := tcpkeepalive.EnableKeepAlive(conn)
ka.SetKeepAliveCount(2)
ka.SetKeepAliveInterval(3 * time.Second)
ka.SetKeepAliveIdle(10 * time.Second)

1 个答案:

答案 0 :(得分:1)

为了简单起见,请不要使用TCP级别的东西来确保您的业务会话的事情。你真正需要的是检测断开的会话,所以继续在业务级别发送乒乓球。你可以简单地计算负载,比如" ping"带有tcp头的字符串,应为30bytes。