TCP 套接字连接是否具有“保持活动状态”?

发布于 2024-08-06 01:42:06 字数 106 浏览 10 评论 0原文

我听说过 HTTP keep-alive,但现在我想打开与远程服务器的套接字连接。
现在,此套接字连接是否会永远保持打开状态,或者是否存在与 HTTP keep-alive 类似的超时限制?

I have heard of HTTP keep-alive but for now I want to open a socket connection with a remote server.
Now will this socket connection remain open forever or is there a timeout limit associated with it similar to HTTP keep-alive?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

泼猴你往哪里跑 2024-08-13 01:42:07

TCP 套接字连接是否具有“保持活动状态”?

简短的回答是,通过TCP Keep-Alive强制执行超时,所以不会,套接字不会永远保持打开状态,但可能会在几个后超时>小时

如果您想在计算机上配置保持活动超时,请参阅下面的“更改 TCP 超时”部分。否则,请通读答案的其余部分,了解 TCP Keep-Alive 的工作原理。

简介

TCP 连接由两个套接字组成,连接的每一端各有一个。当一方想要终止连接时,它会发送一个 FIN 数据包,另一方确认该数据包并关闭其套接字。

然而,在此之前,双方都将无限期地保持套接字打开。这就留下了一种可能性,即一侧可能有意或由于某些错误而关闭其套接字,而不通过 FIN 通知另一端。为了检测这种情况并关闭过时的连接,使用 TCP Keep Alive 过程。

保持活动过程

三个可配置属性决定保持活动如何工作。在 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 步

大多数操作系统默认启用此过程,因此一旦另一端在 2 小时 11 分钟(7200 秒 + 75 * 9 秒)。

陷阱

2 小时默认值

由于默认情况下只有连接空闲两小时后进程才会启动,因此过时的 TCP 连接在被修剪之前可能会停留很长时间。这对于昂贵的连接(例如数据库连接)尤其有害。

Keep-Alive 是可选的,

根据 RFC 1122 4.2.3.6, 响应和/或中继 TCP Keep-Alive 数据包是可选的

实现者可以在其 TCP 实现中包含“keep-alives”,
尽管这种做法并未得到普遍接受。如果保活是
包括在内,应用程序必须能够打开或关闭每个
TCP 连接,并且它们必须默认为关闭。

...

实在是太
重要的是要记住,不包含数据的 ACK 段不是
通过TCP可靠传输。

原因是“保持活动”数据包不包含任何数据,也不是绝对必要的,如果过度使用,可能会堵塞互联网络的管道。

但在实践中,我的经验是,随着带宽变得更便宜,这种担忧随着时间的推移而减少;因此,Keep-Alive 数据包通常不会被丢弃。例如,Amazon EC2 文档给出了间接认可的 Keep-Alive,因此,如果您使用 AWS 进行托管,您可能可以安全地依赖 Keep-Alive,但您的情况可能会有所不同。

更改

每个套接字的

TCP 超时2022 更新: 显然,从 Java 11 开始,您可以在 Java TCP 套接字本身上设置这些。

不幸的是,由于 TCP 连接是在操作系统级别上管理的,旧版本的 Java 不支持在每个套接字级别上配置超时,例如在 java 中.net.Socket。我发现了一些尝试3使用 Java 本机接口 (JNI) 创建调用本机代码来配置这些选项的 Java 套接字,但似乎没有一个得到广泛的社区采用或支持。

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

Linux

当前配置的 TCP Keep-Alive 设置可以在

  • /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 定义了 keepidle keepintvl 以毫秒为单位,而 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

我没有要确认的 Windows 计算机,但您应该在注册表中找到相应的 TCP Keep-Alive 设置

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

< em>脚注

1.请参阅 man tcp 了解更多信息。

2.该数据包通常称为“Keep-Alive”数据包,但在 TCP 规范中,它只是一个常规的 ACK 数据包。像 Wireshark 这样的应用程序能够通过对序列和确认号进行元分析来将其标记为“保持活动”数据包,参考套接字上的先前通信。

3.我从基本的 Google 搜索中找到的一些示例是 lucwilliams/JavaLinuxNetflonatel/libdontdie

Does a TCP socket connection have a "keep alive"?

The short answer is yes there is a timeout enforced via TCP Keep-Alive, so no the socket won't remain open forever but will probably time out after a few hours.

If you would like to configure the Keep-Alive timeout on your machine, see the "Changing TCP Timeouts" section below. Otherwise read through the rest of the answer to learn how TCP Keep-Alive works.

Introduction

TCP connections consist of two sockets, one on each end of the connection. When one side wants to terminate the connection, it sends an FIN packet which the other side acknowledges and both close their sockets.

Until that happens, however, both sides will keep their socket open indefinitely. This leaves open the possibility that one side may close their socket, either intentionally or due to some error, without informing the other end via FIN. In order to detect this scenario and close stale connections the TCP Keep Alive process is used.

Keep-Alive Process

There are three configurable properties that determine how Keep-Alives work. On Linux they are1:

  • tcp_keepalive_time
    • default 7200 seconds
  • tcp_keepalive_probes
    • default 9
  • tcp_keepalive_intvl
    • default 75 seconds

The process works like this:

  1. Client opens TCP connection
  2. If the connection is silent for tcp_keepalive_time seconds, send a single empty ACK packet.1
  3. Did the server respond with a corresponding ACK of its own?
    • No
      1. Wait tcp_keepalive_intvl seconds, then send another ACK
      2. Repeat until the number of ACK probes that have been sent equals tcp_keepalive_probes.
      3. If no response has been received at this point, send a RST and terminate the connection.
    • Yes: Return to step 2

This process is enabled by default on most operating systems, and thus dead TCP connections are regularly pruned once the other end has been unresponsive for 2 hours 11 minutes (7200 seconds + 75 * 9 seconds).

Gotchas

2 Hour Default

Since the process doesn't start until a connection has been idle for two hours by default, stale TCP connections can linger for a very long time before being pruned. This can be especially harmful for expensive connections such as database connections.

Keep-Alive is Optional

According to RFC 1122 4.2.3.6, responding to and/or relaying TCP Keep-Alive packets is optional:

Implementors MAY include "keep-alives" in their TCP implementations,
although this practice is not universally accepted. If keep-alives are
included, the application MUST be able to turn them on or off for each
TCP connection, and they MUST default to off.

...

It is extremely
important to remember that ACK segments that contain no data are not
reliably transmitted by TCP.

The reasoning being that Keep-Alive packets contain no data and are not strictly necessary and risk clogging up the tubes of the interwebs if overused.

In practice however, my experience has been that this concern has dwindled over time as bandwidth has become cheaper; and thus Keep-Alive packets are not usually dropped. Amazon EC2 documentation for instance gives an indirect endorsement of Keep-Alive, so if you're hosting with AWS you are likely safe relying on Keep-Alive, but your mileage may vary.

Changing TCP Timeouts

Per Socket

2022 Update: Apparently, as of Java 11, you may be able to set these on the Java TCP Socket itself.

Unfortunately since TCP connections are managed on the OS level, older versions of Java do not support configuring timeouts on a per-socket level such as in java.net.Socket. I have found some attempts3 to use Java Native Interface (JNI) to create Java sockets that call native code to configure these options, but none appear to have widespread community adoption or support.

Instead, you may be forced to apply your configuration to the operating system as a whole. Be aware that this configuration will affect all TCP connections running on the entire system.

Linux

The currently configured TCP Keep-Alive settings can be found in

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

You can update any of these like so:

# 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

Such changes will not persist through a restart. To make persistent changes, use sysctl:

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

Mac OS X

The currently configured settings can be viewed with 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

Of note, Mac OS X defines keepidle and keepintvl in units of milliseconds as opposed to Linux which uses seconds.

The properties can be set with sysctl which will persist these settings across reboots:

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

Alternatively, you can add them to /etc/sysctl.conf (creating the file if it doesn't exist).

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

Windows

I don't have a Windows machine to confirm, but you should find the respective TCP Keep-Alive settings in the registry at

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

Footnotes

1. See man tcp for more information.

2. This packet is often referred to as a "Keep-Alive" packet, but within the TCP specification it is just a regular ACK packet. Applications like Wireshark are able to label it as a "Keep-Alive" packet by meta-analysis of the sequence and acknowledgement numbers it contains in reference to the preceding communications on the socket.

3. Some examples I found from a basic Google search are lucwilliams/JavaLinuxNet and flonatel/libdontdie.

樱&纷飞 2024-08-13 01:42:07

TCP 套接字保持打开状态直至关闭。

也就是说,在不实际发送数据的情况下很难检测到断开的连接(断开的,如路由器死机等,而不是关闭的),因此大多数应用程序时不时地进行某种 ping/pong 反应,只是为了确保连接实际上仍然有效。

TCP sockets remain open till they are closed.

That said, it's very difficult to detect a broken connection (broken, as in a router died, etc, as opposed to closed) without actually sending data, so most applications do some sort of ping/pong reaction every so often just to make sure the connection is still actually alive.

落在眉间の轻吻 2024-08-13 01:42:07

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

Java Socket API 公开了“keep-alive” " 通过 setKeepAlivegetKeepAlive 方法发送给应用程序。

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

由于没有发送数据,SO_KEEPALIVE只能测试网络连接的活跃度,而不能测试套接字所连接的服务的活跃度。要测试后者,您需要实现一些涉及向服务器发送消息并获取响应的内容。

You are looking for the SO_KEEPALIVE socket option.

The Java Socket API exposes "keep-alive" to applications via the setKeepAlive and getKeepAlive methods.

EDIT: SO_KEEPALIVE is implemented in the OS network protocol stacks without sending any "real" data. The keep-alive interval is operating system dependent, and may be tuneable via a kernel parameter.

Since no data is sent, SO_KEEPALIVE can only test the liveness of the network connection, not the liveness of the service that the socket is connected to. To test the latter, you need to implement something that involves sending messages to the server and getting a response.

一抹淡然 2024-08-13 01:42:07

TCP keepalive 和 HTTP keepalive 是非常不同的概念。在 TCP 中,保活是发送用于检测失效连接的管理数据包。在HTTP中,keepalive表示持久连接状态。

这是来自 TCP 规范,

只有当在一定时间间隔内没有收到连接的数据或确认数据包时,才必须发送保持活动数据包。这个间隔必须是可配置的,并且必须默认不少于两个小时。

正如您所看到的,默认的 TCP keepalive 间隔对于大多数应用程序来说太长了。您可能必须在应用程序协议中添加 keepalive。

TCP keepalive and HTTP keepalive are very different concepts. In TCP, the keepalive is the administrative packet sent to detect stale connection. In HTTP, keepalive means the persistent connection state.

This is from TCP specification,

Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval. This interval MUST be configurable and MUST default to no less than two hours.

As you can see, the default TCP keepalive interval is too long for most applications. You might have to add keepalive in your application protocol.

£冰雨忧蓝° 2024-08-13 01:42:07

如果您位于伪装的 NAT 后面(就像当今大多数家庭用户一样),则外部端口池有限,并且这些端口必须在 TCP 连接之间共享。因此,如果在特定时间段内没有发送数据,伪装 NAT 往往会假设连接已终止。

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

使用 keepalive 既可以减少连接在某个地方被中断的可能性,也可以让您更快地发现连接中断。

If you're behind a masquerading NAT (as most home users are these days), there is a limited pool of external ports, and these must be shared among the TCP connections. Therefore masquerading NATs tend to assume a connection has been terminated if no data has been sent for a certain time period.

This and other such issues (anywhere in between the two endpoints) can mean the connection will no longer "work" if you try to send data after a reasonble idle period. However, you may not discover this until you try to send data.

Using keepalives both reduces the chance of the connection being interrupted somewhere down the line, and also lets you find out about a broken connection sooner.

谁许谁一生繁华 2024-08-13 01:42:07

这里有一些关于 keepalive 的补充文献,其中更详细地解释了它。

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

由于 Java 不允许您控制实际的 keepalive 时间,因此如果您使用的是 Linux 内核(或基于 proc 的操作系统),则可以使用示例来更改它们。

Here is some supplemental literature on keepalive which explains it in much finer detail.

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

Since Java does not allow you to control the actual keepalive times, you can use the examples to change them if you're using a Linux kernel (or proc based OS).

極樂鬼 2024-08-13 01:42:07

对于 Windows,根据 Microsoft 文档

  • KeepAliveTime (REG_DWORD,毫秒,默认不设置,即 7,200,000,000
    = 2 小时) - 类似于 tcp_keepalive_time
  • KeepAliveInterval (REG_DWORD,毫秒,默认情况下未设置,这意味着 1,000 = 1 秒) - 类似于 tcp_keepalive_intvl
  • 从 Windows Vista 开始,没有类似于 tcp_keepalive_probes 的值,值固定为 10 并且无法更改

For Windows according to Microsoft docs

  • KeepAliveTime (REG_DWORD, milliseconds, by default is not set which means 7,200,000,000
    = 2 hours) - analogue to tcp_keepalive_time
  • KeepAliveInterval (REG_DWORD, milliseconds, by default is not set which means 1,000 = 1 second) - analogue to tcp_keepalive_intvl
  • Since Windows Vista there is no analogue to tcp_keepalive_probes, value is fixed to 10 and cannot be changed
把人绕傻吧 2024-08-13 01:42:07

在 JAVA Socket – TCP 连接在操作系统级别进行管理,java.net.Socket 不提供任何内置函数来为每个套接字级别的 keepalive 数据包设置超时。但是我们可以为 java 套接字启用 keepalive 选项,但默认情况下,在过时的 tcp 连接后需要 2 小时 11 分钟(7200 秒)才能处理。此原因连接在清除之前将保持很长一段时间。因此,我们找到了一些解决方案,使用调用本机代码(c++)的Java本机接口(JNI)来配置这些选项。

Windows操作系统

在Windows操作系统中keepalive_time & keepalive_intvl 可以配置,但 tcp_keepalive_probes 不能更改。默认情况下,当 TCP 套接字初始化时,将保持活动超时设置为 2 小时,将保持活动间隔设置为 1 秒。保持活动超时的默认系统范围值可通过 KeepAliveTime 注册表设置进行控制,该设置采用以毫秒为单位的值。

在 Windows Vista 及更高版本中,保持活动探测(数据重新传输)的数量设置为 10 并且无法更改。

在Windows Server 2003、Windows XP和Windows 2000上,保活探针的数量默认设置为5。保活探针的数量是可控的。对于 Windows,Winsock IOCTLs 库用于配置 tcp-keepalive 参数。

int WSAIoctl(
    SocketFD, // descriptor identifying a socket
    SIO_KEEPALIVE_VALS, // dwIoControlCode
    (LPVOID) lpvInBuffer, // pointer to tcp_keepalive struct (DWORD)
    cbInBuffer, // length of input buffer
    NULL, // output buffer
    0, // size of output buffer
    (LPDWORD) lpcbBytesReturned, // number of bytes returned
    NULL, // OVERLAPPED structure
    NULL // completion routine
);

Linux 操作系统

Linux 内置了对 keepalive 的支持,需要启用 TCP/IP 网络才能使用它。程序必须使用setsockopt 接口请求对其套接字进行保活控制。

int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)

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

In JAVA Socket – TCP connections are managed on the OS level, java.net.Socket does not provide any in-built function to set timeouts for keepalive packet on a per-socket level. But we can enable keepalive option for java socket but it takes 2 hours 11 minutes (7200 sec) by default to process after a stale tcp connections. This cause connection will be availabe for very long time before purge. So we found some solution to use Java Native Interface (JNI) that call native code(c++) to configure these options.

Windows OS

In windows operating system keepalive_time & keepalive_intvl can be configurable but tcp_keepalive_probes cannot be change.By default, when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second. The default system-wide value of the keep-alive timeout is controllable through the KeepAliveTime registry setting which takes a value in milliseconds.

On Windows Vista and later, the number of keep-alive probes (data retransmissions) is set to 10 and cannot be changed.

On Windows Server 2003, Windows XP, and Windows 2000, the default setting for number of keep-alive probes is 5. The number of keep-alive probes is controllable. For windows Winsock IOCTLs library is used to configure the tcp-keepalive parameters.

int WSAIoctl(
    SocketFD, // descriptor identifying a socket
    SIO_KEEPALIVE_VALS, // dwIoControlCode
    (LPVOID) lpvInBuffer, // pointer to tcp_keepalive struct (DWORD)
    cbInBuffer, // length of input buffer
    NULL, // output buffer
    0, // size of output buffer
    (LPDWORD) lpcbBytesReturned, // number of bytes returned
    NULL, // OVERLAPPED structure
    NULL // completion routine
);

Linux OS

Linux has built-in support for keepalive which is need to be enabling TCP/IP networking in order to use it. Programs must request keepalive control for their sockets using the setsockopt interface.

int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)

Each client socket will be created using java.net.Socket. File descriptor ID for each socket will retrieve using java reflection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文