处理 TCP 故障的正确机制是啥?
Posted
技术标签:
【中文标题】处理 TCP 故障的正确机制是啥?【英文标题】:What is the proper mechanism for handling TCP failure?处理 TCP 故障的正确机制是什么? 【发布时间】:2017-04-12 00:25:40 【问题描述】:我正在用 C++ 编写一个套接字程序。该程序在一组集群机器上运行。
我刚进入套接字编程,刚刚学会了如何发送和接收。我认为,在程序的长时间运行过程中,一些 TCP 连接可能会丢失。在这种情况下,需要顺利地重新连接服务器和客户端。
我想知道是否有众所周知的基本机制(或算法?协议?)来实现它。我发现有很多不同语义的socket错误代码,这让我很难开始。
谁能推荐任何我可以学习的参考代码?
谢谢,
【问题讨论】:
当一个 TCP 连接失败时,通常是致命的。处理 TCP 连接失败的“标准”方式是简单地关闭连接并尝试重新连接。 【参考方案1】:这并不复杂。对连接不致命的仅有的两个错误代码是:
EAGAIN/EWOULDBLOCK,实际上是同一个号码的两个名字,意思是在一个句号之后,或者select()/poll()/epoll()
这样表示之后,可以重新尝试操作;
EINTR,仅表示“系统调用中断” - 再试一次。
所有其他连接对连接都是致命的,应该导致您关闭它。
【讨论】:
连接可以从非致命错误中恢复,例如ENETUNREACH
。当网络中断被证明是暂时的时,可以立即适应的网络应用程序被破坏。
@Kaz 应用程序只能通过对路由表执行某些操作来从 ENETUNREACH 恢复。
某人/某事对路由表做某事,不一定是应用程序。
在 PPP 拨号时代,我会因为线路中断而让 telnet 死机而烦恼!我修补了该死的源代码以进行正确的错误处理,然后当pppd
恢复连接时,我的 telnet 会话恢复了。
@Kaz '不一定是应用程序:正是如此,我没有另外说明。它可以在外部修复,这就是应用程序不应尝试处理它的原因。【参考方案2】:
实际的具体错误代码无关紧要。如果您有活动的套接字连接,则读取或写入失败表示连接已消失。错误代码可能会给您一些解释,但现在为时已晚。插座没了。没有了。它不复存在了。这是一个前插座。您可以使用错误代码来提出丰富多彩的解释,但这只不过是一些小小的安慰。不管具体原因是什么,但是你的socket已经没了,你必须处理它。
当使用非阻塞套接字时,有某些特定的返回码和errno
值表明套接字仍然正常,但还没有准备好读取或写入任何内容,您必须专门检查,和处理。这是唯一的例外。
另外,EINTR
通常并不一定意味着socket真的坏了;所以这可能是另一个需要检查的异常。
一旦你的插座坏了,唯一的一般设计原则,如果有的话,就是你必须close()
它作为第一件事。文件描述符完全没用。在那之后,接下来要做什么完全取决于您。对于这种情况,没有刻板的规则。通常,应用程序会以某种形式或方式记录错误,或尝试建立另一个连接。通常由您自己决定该怎么做。
关于套接字编程中唯一的“众所周知的基本机制”是显式超时。底层操作系统并不总是能立即检测到网络错误和故障。发生网络问题时,并不总是可以立即检测到。在协议栈声明一个损坏的套接字并给你一个错误指示之前,可能需要几分钟的时间。
因此,如果您正在编写一个特定的应用程序,并且您知道您应该期望在某个规定的时间范围内读取或写入某些内容,那么一个常见的设计模式是编写一个显式超时,并且如果在超时时没有任何反应过期,假设套接字已损坏 -- 即使您没有明确的错误指示,否则 -- close()
它,然后继续下一步。
【讨论】:
读取或写入可能会因 EAGAIN/EWOULDBLOCK 或 EINTR 而失败,其中 none 表示“连接已断开”。如果设置了读取超时,您可以在阻塞模式下获取 EAGAIN/EWOULDBLOCK。以上是关于处理 TCP 故障的正确机制是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Python从入门到精通(十六)Python异常机制2,正确使用Python异常机制的姿势是啥