增强TCP接收方和增强TCP套接字的Keep_alive选项

keep_alive options for boost tcp acceptor and boost tcp socket

本文关键字:增强 TCP Keep alive 选项 套接字      更新时间:2023-10-16

我有几个问题,都与keep_alive有关。

  • basic_socket_acceptor::keep_alivebasic_stream_socket::keep_alive有什么区别?什么时候用哪个?
  • 我们需要用keep_alive代替ip::tcp::acceptor吗?这对我来说没有意义,因为对于接受者来说没有连接,但是对于它也有一个keep_alive 选项,因此混淆。
  • 如果设置了keep_alive,那么Boost Asio检测到连接断开时的行为是什么?它如何/何时通知用户代码?它会抛出异常吗?如果有,是哪个例外?我在文档中没有看到任何这样的细节。

basic_socket_acceptor::keep_alive和basic_stream_socket: keep_alive吗?什么时候用哪个?

两者相同。在文档中,它出现在basic_socket_acceptorbasic_stream_socket下,因为它们都派生自socket_base,其中keepalive选项实际上是可见的(它是一个类型定义)。

根据文档中的示例,您将始终这样使用它:

boost::asio::socket_base::keep_alive option(true);
socket.set_option(option);

我们需要为ip::tcp::acceptor使用任何类型的keep_alive吗?

不,你不需要,也不能。set_option无论如何只能在套接字对象上调用(我相信只有在套接字之后才是opened)。

如果设置了keep_alive,那么Boost Asio在设置keep_alive时的行为是什么检测到连接断开?

这取决于平台。在linux上,当keep_alive探测失败时,您将获得broken pipe错误或EPOLLERR/EPOLLHUP

UPDATE(来自我下面的评论):

此错误未传播到用户代码。因此,您可能需要实现应用程序级别的ping或使用超时套接字选项。

basic_socket_acceptor::keep_alivebasic_stream_socket::keep_alive相同。文档指出,它们都继承自定义socket_base::keep_alive选项的socket_base类。

basic_stream_socket::keep_alive

继承自socket_base.

发送keepalive的Socket选项。

虽然侦听套接字上的keep-alive对侦听套接字并不直接有用,但在某些系统上,新接受的套接字继承了侦听套接字的一些套接字选项。继承的套接字选项通常是会影响TCP三次握手的选项,必须在accept()返回之前完成,例如SO_KEEPALIVE。因此,Asio支持在接收者上设置keep-alive选项;但是,Asio不复制套接字选项到新的套接字。

keep-alive特性允许操作被通知连接断开,这是由keep-alive机制1决定的。因此,当keep-alive探测失败时,套接字上的下一个Asio写操作将失败2,以与提供其他错误码相同的方式将error_code传递给应用程序。应该查阅操作系统的文档,以确定写入操作的预期错误代码:

  • 在Windows上,WSASend()被记录为返回WSAENETRESET (boost::asio::error:: connection_reset)
  • 在Linux上,错误将根据keep-alive探测失败的方式而变化。如果没有响应,则会出现ETIMEOUT (boost::asio::error::timed_out)。如果在响应keep-alive探测时返回一个ICMP错误,那么将返回相关的ICMP错误。例如,可以观察到EHOSTUNREACH (boost::asio::error::host_unreachable)返回

<一口>1. 参见RFC 1122对Internet主机通信层的要求2. SO_KEEPALIVE通过SIGPIPE信号通知线程向套接字写入,但是Asio明确地在写操作时禁用接收SIGPIPE。因此,底层系统调用将返回相关的错误

这取决于您所运行的平台。在linux上,如果您完全执行以下操作,

boost::asio::socket_base::keep_alive option(true);
socket.set_option(option);

则基本上可以保护您免受可能发生的轻微网络中断并导致套接字上的读写错误。如果你在套接字指针上设置keep_alive为true,那么有几种特定的方法可以检测你正在读写的套接字上的错误:

  • 首先,可以通过实现在对等体之间间隔发送健康数据包的乒乓机制来检测套接字错误。

  • 或者,当你从套接字返回boost::asio::error::eof错误时,你也可以检测到一个错误,这基本上意味着对等端已经关闭了连接。请注意,如果连接被对端关闭,对套接字的读取仍然可以返回boost::asio::error::eof错误。