【发布时间】:2018-04-18 09:17:21
【问题描述】:
我有一个用于 Linux 中 TCP 客户端和服务器的 C/C++ 应用程序。
假设在 TCP 连接到位后,服务器和客户端都没有在很长一段时间内发送任何数据。他们甚至不会互相发送任何心跳。
通过 TCP 协议,连接应该存在多长时间?
连接是否因不活动而断开?
如果是这样,是否有任何套接字选项可以指定或定义任何类型的超时行为?
【问题讨论】:
标签: c++ sockets networking tcp
我有一个用于 Linux 中 TCP 客户端和服务器的 C/C++ 应用程序。
假设在 TCP 连接到位后,服务器和客户端都没有在很长一段时间内发送任何数据。他们甚至不会互相发送任何心跳。
通过 TCP 协议,连接应该存在多长时间?
连接是否因不活动而断开?
如果是这样,是否有任何套接字选项可以指定或定义任何类型的超时行为?
【问题讨论】:
标签: c++ sockets networking tcp
恐怕唯一明智的答案应该是视情况而定。
一个 TCP 连接可以在两端之间使用多个中间中继。每个组件(读取每个端和每个中继)都可以有自己的策略来关闭不活动的连接。
一个常见的解决方法是使用keepalive 作为一个可选 TCP 功能。当连接空闲超过定义的超时时间时,它由一端发送的空包组成。对等方应以 ACK 应答,即使它不支持 keepalive 扩展,这足以在 TCP 级别保持连接处于活动状态。
例如,在 Linux 中,keepalive 可以在内核级别设置,并且对于所有新的 TCP 连接都将处于活动状态。这可能是个坏主意,因为默认情况下 keepalive 是关闭的,以避免网络开销。从参考页面:
涉及keepalive的程序使用三个用户驱动的变量:
tcp_keepalive_time
最后一个数据包发送(简单的ACKs不被认为是数据)和第一个keepalive探测之间的间隔;在连接被标记为需要保持连接后,不再使用此计数器 tcp_keepalive_intvl
后续keepalive探测之间的间隔,无论连接在此期间交换了什么
tcp_keepalive_probes
在考虑连接失效并通知应用层之前要发送的未确认探测数
它们可以设置为例如sysctl(8):
# sysctl -w \ > net.ipv4.tcp_keepalive_time=600 \ > net.ipv4.tcp_keepalive_intvl=60 \ > net.ipv4.tcp_keepalive_probes=20 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 60 net.ipv4.tcp_keepalive_probes = 20
也可以使用setsockopt为应用程序级别的某些连接设置它:
/* Set the option active */ int optval = 1; socklen_t optlen = sizeof(optval); if(setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { perror("setsockopt()"); close(s); exit(EXIT_FAILURE); }
【讨论】:
通过 TCP 协议,连接应该存在多长时间?
永远。
连接是否因不活动而断开?
没有。
如果是这样,是否有任何套接字选项可以指定或定义任何类型的超时行为?
支持 SO_RCVTIMEO。这为recv() 方法和朋友提供了读取超时。
【讨论】:
【讨论】: