Kev*_*oyd 77 java sockets tcp http keep-alive
我听说过HTTP keep-alive但是现在我想打开一个与远程服务器的套接字连接.
现在这个套接字连接是否会永远保持打开状态,或者是否存在与之相关的超时限制,类似于HTTP keep-alive?
Cor*_*ein 82
现在这个套接字连接是否会永远保持打开状态,或者是否存在与之相关的超时限制,类似于HTTP keep-alive?
简短的回答是,是的,有一个超时,它通过TCP Keep-Alive强制执行.
如果要配置保持活动超时,请参阅下面的"更改TCP超时"部分.
TCP连接由两个插槽组成,每个插槽位于连接的两端.当一方想要终止连接时,它会发送RST另一方确认的数据包并关闭其套接字.
然而,在此之前,双方将无限期地保持其套接字开放.这使得一方可能有意或由于某些错误而关闭其插座,而无需通知另一端RST.为了检测此场景并关闭过时连接,使用TCP Keep Alive进程.
有三个可配置属性可确定Keep-Alives的工作方式.在Linux上他们是1:
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
这个过程是这样的:
tcp_keepalive_time几秒钟,则发送一个空ACK数据包.1ACK自己的相应方式响应?
tcp_keepalive_intvl几秒钟,然后发送另一个ACKACK已发送的探测数等于tcp_keepalive_probes.RST并终止连接.默认情况下,在大多数操作系统上启用此过程,因此一旦另一端无响应2小时11分钟(7200秒+ 75*9秒),则会定期修剪死TCP连接.
由于默认情况下连接空闲两小时后才开始进程,因此过时的TCP连接可能会在修剪之前停留很长时间.这对于诸如数据库连接之类的昂贵连接尤其有害.
根据RFC 1122 4.2.3.6,响应和/或中继TCP Keep-Alive数据包是可选的:
实现者可以在他们的TCP实现中包含"keep-alives",尽管这种做法并不是普遍接受的.如果包含keep-alives,应用程序必须能够为每个TCP连接打开或关闭它们,并且它们必须默认为关闭.
...
记住TCP不能可靠地传输不包含数据的ACK段是非常重要的.
原因是Keep-Alive数据包不包含任何数据,并且不是严格必要的,如果过度使用,可能会堵塞互联网的管道.
然而,在实践中,我的经验是,随着带宽变得越来越便宜,这种担忧随着时间的推移逐渐减少; 因此,通常不会丢弃Keep-Alive数据包.例如,亚马逊EC2文档间接认可Keep-Alive,因此如果您使用AWS托管,您可能会安全地依赖Keep-Alive,但您的里程可能会有所不同.
不幸的是,由于TCP连接是在操作系统级别上进行管理的,因此Java不支持在每个套接字级别上配置超时,例如java.net.Socket.我发现了一些尝试3使用Java本机接口(JNI)来创建调用本机代码来配置这些选项的Java套接字,但似乎没有一个广泛的社区采用或支持.
相反,您可能被迫将配置作为一个整体应用于操作系统.请注意,此配置将影响整个系统上运行的所有TCP连接.
可以在中找到当前配置的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
Run Code Online (Sandbox Code Playgroud)
这种变化不会在重启后持续存在.要进行持久更改,请使用sysctl:
sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
Run Code Online (Sandbox Code Playgroud)
可以使用以下方式查看当前配置的设置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
Run Code Online (Sandbox Code Playgroud)
值得注意的是,Mac OS X定义keepidle并keepintvl以毫秒为单位,而不是使用秒的Linux.
可以设置属性,sysctl以便在重新启动后保留这些设置:
sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
Run Code Online (Sandbox Code Playgroud)
或者,您可以将它们添加到/etc/sysctl.conf(如果文件不存在,则创建该文件).
$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3
Run Code Online (Sandbox Code Playgroud)
我没有Windows机器来确认,但您应该在注册表中找到相应的TCP Keep-Alive设置
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
脚注
1.有关man tcp更多信息,请参阅.
2.此数据包通常称为"保持活动"数据包,但在TCP规范中,它只是一个常规ACK数据包.像Wireshark这样的应用程序能够通过元数据分析将其标记为"保持活动"数据包,它包含参考插槽上先前通信所包含的序列和确认号.
我从谷歌基本搜索中找到的一些例子是lucwilliams/JavaLinuxNet和flonatel/libdontdie.
Mat*_*ley 67
TCP套接字保持打开状态,直到它们关闭.
也就是说,在没有实际发送数据的情况下检测断开连接(断路,如路由器死亡等,而非关闭)非常困难,因此大多数应用程序每隔一段时间就会做一些ping/pong反应,以确保连接仍然存在.
Ste*_*n C 53
您正在寻找SO_KEEPALIVE套接字选项.
在的Java的Socket API暴露了"保活"通过应用程序setKeepAlive和getKeepAlive方法.
编辑:SO_KEEPALIVE在OS网络协议栈中实现,不发送任何"真实"数据.保持活动间隔取决于操作系统,并且可以通过内核参数进行调整.
由于没有数据发送,SO_KEEPALIVE只能测试网络连接的活跃程度,而不能测试套接字所连接的服务的活跃程度.要测试后者,您需要实现一些涉及向服务器发送消息并获得响应的内容.
ZZ *_*der 33
TCP keepalive和HTTP keepalive是非常不同的概念.在TCP中,keepalive是为检测过时连接而发送的管理数据包.在HTTP中,keepalive表示持久连接状态.
这是来自TCP规范,
只有在间隔内没有收到连接的数据或确认数据包时,才能发送保持活动的数据包.这个间隔必须是可配置的,必须默认不少于两个小时.
如您所见,对于大多数应用程序,默认TCP keepalive间隔太长.您可能必须在应用程序协议中添加keepalive.
Art*_*ius 23
如果你是伪装NAT的背后(如今大多数家庭用户都是这样),那么外部端口池有限,这些端口必须在TCP连接之间共享.因此,伪装NAT倾向于假设如果在特定时间段内没有发送数据则终止连接.
此问题和其他此类问题(两个端点之间的任何位置)可能意味着如果您尝试在合理的空闲时段之后发送数据,则连接将不再"起作用".但是,在尝试发送数据之前,您可能不会发现这一点.
使用Keepalive既可以降低连接在线路中断的可能性,也可以让您更快地找到断开的连接.
| 归档时间: |
|
| 查看次数: |
132157 次 |
| 最近记录: |