1 回答
TA贡献1875条经验 获得超5个赞
你显然不能。
但这原则上与 Go 无关,而是关于 TCP/IP。
为什么你不能有多个方面:
这样的检查——如果存在的话——本质上是活泼的:例如,一旦检查返回“一切正常”,远程端就可以向你发送一个带有
RST
.这很像在尝试读取文件之前检查文件系统上的文件是否存在:一旦检查询问文件系统文件是否存在,并且它回答“是”,任何其他进程都可以删除该文件,因此尝试打开相信存在的文件将失败。
还要考虑一个完全可行的可能性,即您的进程与系统中运行的其他进程竞争 CPU 时间:当内核剥夺您的进程的 CPU 时,您的程序代码中看起来像两个相邻的操作可能被许多挂钟时间分开时间,无论什么原因。
流行内核的 TCP/IP 堆栈不会公开“TCP 连接健康”的概念。
例如,假设您已经向远程端发送了几个字节,并且本地系统上的 TCP 堆栈等待听到远程 TCP 堆栈确认它们的接收。
您无法让 TCP 堆栈告诉您的用户空间代码似乎“停止”了某些东西。远程端的情况更糟:如果远程方试图向您发送一些东西并且由于某种原因而停止,它根本无法将这个事实传达给您:因为通信链接毕竟是停止的,所以没有通信是可能的。
仍然存在几种方法来解决这个问题。
在您的应用程序级协议中实现“pings”(“heartbeats”——正如@Adrian 在他们的评论中所建议的——是此类功能的另一个流行名称)。
比如说,如果参与通信的一方在指定的时间段内没有发送任何信息,它必须发送一些“ping”消息,然后期望远程端用“pong”消息回复它,这应该发生在配置的时间范围内;如果 pong 没有在该时间范围内到达,您认为通信链接已损坏。
net.TCPConn.SetKeepalive*
通过使用其方法在您的连接上启用 TCP keepalives,并依靠它们主动检测通信中断。如果连接处于空闲状态,此机制使 TCP 堆栈向远程端发送特殊的探测帧。
如果这样的探测失败,内核将关闭套接字,这将在您的代码中显示为“套接字准备就绪”事件,最近尝试读取和/或写入它失败并出现错误。
请注意,TCP keepalive 是一种复杂的野兽,您可能需要研究它们是如何工作的,链路两端的内核是否需要调整,并在出现人工链路故障的情况下测试您的解决方案。
你可以从这里开始你的旅程。
- 1 回答
- 0 关注
- 178 浏览
添加回答
举报