猿问

go中如何查询TCP连接状态?

在 TCP 连接的客户端,我尝试尽可能多地重用已建立的连接,以避免每次需要连接时拨号的开销。从根本上说,它是连接池,虽然从技术上讲,我的池大小恰好是一个。


我遇到了一个问题,如果连接空闲时间足够长,另一端会断开连接。我试过使用类似以下的东西来保持连接活跃:


err = conn.(*net.TCPConn).SetKeepAlive(true)

if err != nil {

    fmt.Println(err)

    return

}

err = conn.(*net.TCPConn).SetKeepAlivePeriod(30*time.Second)

if err != nil {

    fmt.Println(err)

    return

}

但这没有帮助。事实上,它导致我的连接更快关闭。我很确定这是因为(在 Mac 上)这意味着连接健康状况在 30 秒后开始被探测,然后以 30 秒的间隔被探测 8 次。 服务器端一定不支持 keepalive,所以在 4 分 30 秒后,客户端断开连接。


我可能无法使空闲连接无限期地保持活动状态,如果有某种方法至少可以检测到连接已关闭,以便我可以无缝地用新连接替换它,那绝对没问题。唉,即使在阅读了所有文档并搜索博客圈寻求帮助之后,我也找不到任何方法来查询 TCP 连接的状态。


一定有办法。有没有人对如何实现这一点有任何见解?非常感谢任何这样做的人!


编辑:


理想情况下,我想学习如何在不使用第三方库的情况下使用纯 go 来处理低级别的问题。当然,如果有一些图书馆这样做,我不介意指出它的方向,这样我就可以看到他们是如何做到的。


跃然一笑
浏览 1058回答 2
2回答

qq_遁去的一_1

套接字 api 不允许您访问连接状态。您可以通过各种方式从内核(/proc/net/tcp[6]例如在 linux 上)查询当前状态,但这并不能保证进一步发送会成功。我在这里有点困惑。我的客户只发送数据。除了确认数据包外,服务器不会返回任何内容。阅读似乎不是确定连接状态的合适方法,因为有注意阅读。套接字 API 被定义为通过读取返回 0 字节来检测关闭的连接。这就是它的工作方式。在 Go 中,这被转换为 Read 返回io.EOF。这通常是检测断开连接的最快方法。那么我是否应该只发送并处理发生的任何错误?如果是这样,这是一个问题,因为我观察到在尝试通过损坏的管道发送时,我通常根本不会收到任何错误——这似乎完全错误如果您仔细观察 TCP 的工作原理,就会发现这是预期的行为。如果连接在远程端关闭,那么您的第一次发送将触发来自服务器的 RST,完全关闭本地连接。您要么需要从连接中读取数据以检测关闭,或者如果您再次尝试发送,您将收到一个错误(假设您等待数据包来回的时间足够长),例如 linux 上的“管道损坏” .澄清一下......我可以拨号,拔下以太网电缆,然后仍然没有错误地发送。显然,消息没有通过,但我没有收到任何错误如果连接确实中断了,或者服务器完全没有响应,那么您将数据包发送到任何地方。TCP 堆栈无法区分真正慢的数据包、数据包丢失、拥塞或连接断开之间的区别。系统需要等待重传超时,并在失败之前重试数据包多次。仅重试的标准配置可能需要 13 到 30 分钟才能触发错误。你可以在你的代码中做的是开启保活。这将更快地通知您连接断开,因为空闲连接始终在测试中。从套接字读取。要么进行并发读取,要么使用 select/poll/epoll 检查要先读取的内容(Go 通常使用第一个)为所有内容设置超时(Go 中的截止日期)。如果您不希望从连接中获得任何数据,那么在 Go 中检查关闭的连接非常容易;调度一个 goroutine 从连接中读取,直到出现错误。notify := make(chan error)go func() {&nbsp; &nbsp; buf := make([]byte, 1024)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; n, err := conn.Read(buf)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; notify <- err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if n > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("unexpected data: %s", buf[:n])&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}()

慕哥9229398

按照设计,没有“TCP 连接状态”这样的东西。只有当你发送一些东西时才会发生什么。没有任何级别的 TCP API 可以告诉您 TCP 连接的当前状态,在任何级别上都没有硅。你必须尝试使用它。如果您要发送 keepalive 探测,服务器别无选择,只能做出适当的响应。服务器甚至不知道它们是保活的。他们不是。它们只是重复的 ACK。支持keepalive就是支持发送keepalive。
随时随地看视频慕课网APP

相关分类

Go
我要回答