【发布时间】: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