【问题标题】:The right way to detect tcp broken connection ? Manual keepalive idle , and don't worked SetWriteDeadLine检测 tcp 断开连接的正确方法?手动 keepalive idle ,并且不工作 SetreadDeadLine
【发布时间】:2015-08-26 23:02:45
【问题描述】:

我的 TCP 连接有问题。

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

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

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

首先我在 go SetKeepAlive(true)SetKeepAlivePeriod(10 * time.Second) 中使用。它有效,但没有我需要的那么快。因为去 SetKeepAlivePeriod,所以将 tcp keepalive time(idle)tcp keepalive interval 设置为相同。例如在 linux tcp keepalive retry=8 中,则在 (10 + 8*10) = 90sec = 1 min 30sec 之后检测到连接问题。它非常非常慢:(。如何手动设置空闲和间隔?我在看这个库https://github.com/felixge/tcpkeepalive,但我不信任这个库,因为,在这个库中,套接字 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{})
}

当客户端连接断开后,我将一些数据写入连接,方法 Write 返回 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)

【问题讨论】:

  • 设置套接字读取超时。
  • @EJP 如何在 golang 中做到这一点?
  • @sintanial: conn.SetReadDeadline

标签: sockets networking tcp go


【解决方案1】:

为了简单起见,请不要使用 TCP 级别的东西来确保您的业务会话的东西。您真正需要的是检测损坏的会话,因此请继续在业务级别发送乒乓球。您可以简单地计算负载,例如带有 tcp 标头的“ping”字符串,应该是 30 字节。

【讨论】:

  • "ping" 是四个字节; TCP 标头至少为 20 字节; IP头是另外20个。总共44个。
  • 我错了,它应该小于 30 字节,而不是 20,因为 ip 不应该包括在内。因为几乎所有东西都有ip层,我们无法避免。
  • 那么它是免费的吗?摆脱它。 44 字节。
  • @EJP 1st,tcp keep live等方式也需要IP超载。 2,如果你想计算整个堆栈中的字节数,我们需要 802.3/802.11/3G-mobile/4G-mobile/EDGE/GPRS ... 所有级别。最后,那不是闹剧。
  • @JiangYD 为什么是商务会议?我需要检测断开的连接,因为这个问题发明了像keepalive这样的心跳。为什么我必须在 tcp 上使用我的实现?有人向我解释为什么 SetWriteDeadline 不起作用?
猜你喜欢
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多