做一个TCP套接字连接有一个“保活”?(Does a TCP socket connection h

2019-07-19 16:48发布

我听说HTTP保活的,但现在我要打开与远程服务器的套接字连接。
现将此套接字连接保持打开状态永远还是有与之关联的超时限制类似于HTTP保持活动?

Answer 1:

TCP套接字保持打开状态,直到它们被关闭。

这就是说,它是非常困难的检测断开的连接(破碎,如在路由器死亡等,而不是封闭的),而不实际发送数据,因此大多数应用程序做一些让平/乒乓反应,每隔一段时间,以确保公正连接仍然活着的实际。



Answer 2:

现将此套接字连接保持打开状态永远还是有与之关联的超时限制类似于HTTP保持活动?

简单的答案是, 是的 ,有超时,它是通过TCP保持活动的执行。

如果你想配置保持活动超时,请参阅“更改TCP超时”部分。

介绍

TCP连接包括两个插座,一个在连接的每一端的。 当一方要终止连接,它发送一个RST将对方承认并在附近的座包。

在此之前,但是,双方将保持其套接字打开无限。 这使得打开一个侧面可以关闭他们的插座,无论是有意还是由于一些错误,不通过通知另一端的可能性RST 。 为了检测这种情况下,关闭陈旧连接的TCP保活处理时使用。

保活处理

有三种确定如何保持活动的工作配置的属性。 在Linux上,他们是1:

  • tcp_keepalive_time
    • 默认7200秒
  • tcp_keepalive_probes
    • 默认9
  • tcp_keepalive_intvl
    • 默认75秒

这个过程是这样的:

  1. 客户端打开TCP连接
  2. 如果连接是沉默tcp_keepalive_time秒,发送单个空ACK包。 1
  3. 难道服务器与相应的响应ACK自己的呢?
    • 没有
      1. 等待tcp_keepalive_intvl秒钟,然后再发送ACK
      2. 重复,直到数量ACK已发送探测等于tcp_keepalive_probes
      3. 如果没有响应在这一点上被接收,发送RST并终止连接。
    • :返回步骤2

这个过程是通过默认在大多数操作系统使能,并且因此死TCP连接定期修剪一次的另一端未回应2小时11分(7200秒+ 75 * 9秒)。

陷阱

2小时默认

由于该进程将不会启动,直到连接已空闲了两个小时在默认情况下,陈旧的TCP连接可以被修剪前磨蹭了很长一段时间。 这可能是昂贵的连接,如数据库连接尤其有害。

保持活动是可选

根据RFC 1122 4.2.3.6 ,响应和/或中继TCP保活分组。 可选

实现者可能在其TCP实现“保持活动”,虽然这种做法没有被普遍接受。 如果保持有效指示包括,应用程序必须能够开启或关闭每个TCP连接时,它们必须默认为关闭。

...

重要的是要记住,不包含任何数据不可靠的TCP传输的ACK段是非常重要的。

其理由在于保活分组不包含任何数据,并没有绝对必要的风险,如果过度使用堵塞的interwebs的管子。

然而在实践中 ,我的经验是,这种担忧已经减少随着时间的推移带宽越来越便宜; 因而保活分组通常不下降。 亚马逊EC2的文档 ,例如使保持活动的间接认可,因此,如果您正在使用AWS托管你很可能安全的依靠保持活动,但您的里程可能会有所不同。

更改TCP超时

每个插槽

不幸的是,因为TCP连接在操作系统级别管理,Java不支持在每个套接字级别,如配置超时java.net.Socket 。 我已经发现了一些尝试3使用Java本地接口(JNI)来创建调用本地代码来配置这些选项的Java插座,但没有出现有社会各界的广泛采纳和支持。

相反,你可能会被迫配置应用到操作系统作为一个整体。 请注意,此配置将影响整个系统上运行的所有TCP连接。

Linux的

当前配置的TCP保持活动的设置中可以找到

  • /proc/sys/net/ipv4/tcp_keepalive_time
  • /proc/sys/net/ipv4/tcp_keepalive_probes
  • /proc/sys/net/ipv4/tcp_keepalive_intvl

您可以更新任何这些像这样:

# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes
$ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time
# Send three Keep-Alive probes...
$ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
# ... spaced 10 seconds apart.
$ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl

这样的变化将不通过重启坚持。 要再接再厉变化,使用sysctl

sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10

的Mac OS X

当前配置的设置可以被看作sysctl

$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt"
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepcnt: 8

值得注意的是,Mac OS X的定义keepidlekeepintvl中,而不是Linux的它采用秒单位为毫秒。

性能可与设置sysctl将坚持在重新启动后这些设置:

sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000

或者,也可以将它们添加到/etc/sysctl.conf (创建文件,如果不存在的话)。

$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3

视窗

我没有Windows机器确认,但你应该在注册表中找到相应的TCP保持活动设置

\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters

脚注

1.见man tcp获取更多信息。

2.该分组经常被称为“保持活动”分组,但是TCP说明书内它只是一个普通的ACK分组。 Wireshark之类的应用程序可以将其标记为通过它包含参照插座上的前通信的序列号和确认号的荟萃分析了“保持活动”包。

3.一些例子,我从一个基本的谷歌搜索发现是lucwilliams / JavaLinuxNet和flonatel / libdontdie 。



Answer 3:

您正在寻找SO_KEEPALIVE套接字选项。

在的Java的Socket API暴露了“保持活动”,以通过应用setKeepAlivegetKeepAlive方法。

编辑:SO_KEEPALIVE在OS网络协议栈中实现,而不发送任何“真实”的数据。 保活间隔取决于操作系统,并且可以是通过内核参数可调。

由于没有数据被发送时,SO_KEEPALIVE只能测试网络连接,而不是将插座连接到服务的活跃度的活跃度。 为了测试后,您需要实现的东西,涉及将消息发送到服务器并得到响应。



Answer 4:

TCP保活和HTTP保持连接是不同的概念。 在TCP,保活是发送到检测无效连接的管理包。 在HTTP中,保活意味着持续连接状态。

这是TCP规范,

保活当已经接收到一个时间间隔内的连接没有数据或确认数据包的数据包必须只发送。 这个间隔必须是可配置的,必须默认为不超过两小时不到。

正如你所看到的,默认的TCP存活时间间隔对于大多数应用太长。 您可能需要在应用程序协议添加存活。



Answer 5:

如果你落后伪装NAT(大多数家庭用户这些天),有外部端口有限的游泳池,而这些必须的TCP连接之间共享。 因此伪装的NAT倾向于假定如果没有数据已被用于在特定时间段发送的连接已经终止。

这和其他此类问题(在两个端点之间的任何地方)可能意味着连接将不再是“工作”,如果你尝试一个讲理的空闲一段时间后发送数据。 但是,直到您尝试发送数据,你可能不会发现这一点。

使用保活既降低了连接的可能性正在某处中断上下行,并且还可以让你了解断开连接越快。



Answer 6:

下面是一些存活补充文献这就解释了它在更精细的细节。

http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO

由于Java不允许你控制的实际存活时间,你可以使用的例子,如果您使用的是Linux内核(或PROC基于OS),以改变它们。



Answer 7:

在JAVA插座 - TCP连接在操作系统级别管理,java.net.Socket中不提供任何内置的功能可为保活包超时在每个插座的水平。 但是,我们可以启用Java套接口keepalive选项,但默认情况下需要2小时11分(7200秒),一个陈旧的TCP连接后进行处理。 这导致连接将被用于速效清洗之前很长一段时间。 因此,我们发现了一些解决方案中使用Java本地接口(JNI)调用本机代码(C ++)来配置这些选项。

**** Windows操作系统****

在操作系统keepalive_time&keepalive_intvl可以是可配置但tcp_keepalive_probes不能change.By默认窗口,当TCP套接字被初始化设定保持活动超时到2小时,保活间隔为1秒。 保持连接超时的默认系统范围值是通过KeepAliveTime的注册表设置这需要以毫秒为单位的值控制。

在Windows Vista和更高版本,保活探头(数据重传)的数量设置为10,不能更改。

在Windows Server 2003,Windows XP和Windows 2000中,默认设置保持有效探测的数量为5保活探头数量是可控的。 对于Windows的Winsock的IOCTL库用来配置TCP的保活参数。

INT的WSAIoctl(SocketFD,//描述符识别插座SIO_KEEPALIVE_VALS,// dwIoControlCode(LPVOID)lpvInBuffer,//指针TCP_KEEPALIVE结构(DWORD)cbInBuffer,//输入缓冲器NULL,//输出缓冲器0,//尺寸的长度输出缓冲器(LPDWORD)lpcbBytesReturned,//字节数返回NULL,// OVERLAPPED结构NULL //完成例程);

Linux操作系统

Linux已经内置了对存活是必须启用TCP / IP才能使用它的网络支持。 方案必须请求使用setsockopt接口眼窝存活控制。

INT setsockopt的(INT插座,INT水平,INT OPTNAME,常量无效* optval的,socklen_t的optlen)

每个客户端套接字将使用java.net.Socket中被创建。 每个套接字文件描述符ID将检索使用Java反射。



Answer 8:

根据到Windows 微软文档

  • KeepAliveTime的(REG_DWORD,毫秒,默认情况下没有被设置,这意味着72亿= 2小时) - 类似物tcp_keepalive_time
  • 的KeepAliveInterval(REG_DWORD,毫秒,默认情况下没有被设置,这意味着1000 = 1秒) - 类似物tcp_keepalive_intvl
  • 由于Windows Vista中没有模拟到tcp_keepalive_probes,值固定为10,不能改变


文章来源: Does a TCP socket connection have a “keep alive”?