java.net.Socket TCP keep-alive 用法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31810668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.net.Socket TCP keep-alive usage
提问by LPD
How to use java.net.Socket
setKeepAlive(boolean b)
API?
如何使用java.net.Socket
setKeepAlive(boolean b)
API?
I am hosting a simple server using Socket
.
The clients can connect and send data. I will not close the connection unless the client sends end of stream. The client can continue to hold a connection for any length of time. Data transfer will be going on, but suddenly I see that there is a connection loss without any logs whatsoever. Once the client is restarted (not server), the transmission begins again.
I am not setting any timeout
as by default it is infinity. I want to understand what setKeepAlive
actually does so that I will be able to decide whether I need to set that to true
.
Can someone help me understand the same? thanks.
我正在托管一个简单的服务器,使用Socket
. 客户端可以连接并发送数据。除非客户端发送流结束,否则我不会关闭连接。客户端可以在任何时间段内继续保持连接。数据传输将继续进行,但突然我发现连接丢失,没有任何日志。一旦客户端(不是服务器)重新启动,传输将再次开始。我没有设置任何timeout
,因为默认情况下它是无穷大。我想了解setKeepAlive
实际执行的操作,以便我能够决定是否需要将其设置为true
. 有人可以帮我理解相同的吗?谢谢。
回答by dsh
As the documentation for setKeepAlive()
says, it will enable (or disable) the SO_KEEPALIVE
option on the socket.
正如文档setKeepAlive()
所说,它将启用(或禁用)SO_KEEPALIVE
套接字上的选项。
When the keepalive option is set for a TCP socket and no data has been exchanged across the socket in either direction for 2 hours (NOTE: the actual value is implementation dependent), TCP automatically sends a keepalive probe to the peer. This probe is a TCP segment to which the peer must respond. One of three responses is expected: 1. The peer responds with the expected ACK. The application is not notified (since everything is OK). TCP will send another probe following another 2 hours of inactivity. 2. The peer responds with an RST, which tells the local TCP that the peer host has crashed and rebooted. The socket is closed. 3. There is no response from the peer. The socket is closed. The purpose of this option is to detect if the peer host crashes. Valid only for TCP socket: SocketImpl
当为 TCP 套接字设置了 keepalive 选项并且 2 小时内没有在任一方向上通过套接字交换数据时(注意:实际值取决于实现),TCP 会自动向对等方发送一个 keepalive 探测。此探测是对等方必须响应的 TCP 段。预期三种响应之一: 1. 对等方以预期的 ACK 响应。不会通知应用程序(因为一切正常)。TCP 将在另外 2 小时不活动后发送另一个探测。2. 对端用 RST 响应,它告诉本地 TCP 对端主机已经崩溃并重新启动。插座已关闭。3. 对端无响应。插座已关闭。此选项的目的是检测对等主机是否崩溃。仅对 TCP 套接字有效:SocketImpl
Hereis another reference explaining the SO_KEEPALIVE
option.
这是另一个解释该SO_KEEPALIVE
选项的参考资料。
Note that in networking, connections can be lost at any time for a myriad of reasons. If the connection traverses a NAT router, the entry in the NAT table could expire (when the connection is idle) and the connection is lost due to that. The client could cease to function, or be suspended (especially laptops and mobile devices), or a cable could be disconnected, or WiFi (or cellular) signal could be interfered with, or ... the list can go on. Your server needs to be written to cope gracefully with loss of connection.
请注意,在网络中,由于各种原因,连接可能随时丢失。如果连接穿过 NAT 路由器,则 NAT 表中的条目可能会过期(当连接空闲时)并且连接因此而丢失。客户端可能会停止运行,或被暂停(尤其是笔记本电脑和移动设备),或者电缆可能会断开,或者 WiFi(或蜂窝)信号可能会受到干扰,或者......列表可以继续。您的服务器需要编写为优雅地处理连接丢失。
回答by Suganya Vinayakam
I face the similar problem in my case
在我的情况下,我面临类似的问题
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.
在 JAVA Socket – TCP 连接是在 OS 级别管理的,java.net.Socket 不提供任何内置函数来设置每个套接字级别的 keepalive 数据包超时。但是我们可以为 java socket 启用 keepalive 选项,但默认情况下需要 2 小时 11 分钟(7200 秒)来处理一个陈旧的 tcp 连接。此原因连接将在清除之前可用很长时间。因此,我们找到了一些使用 Java Native Interface (JNI) 调用本机代码 (c++) 来配置这些选项的解决方案。
****Windows OS****
****Windows 操作系统****
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.
在 windows 操作系统中,keepalive_time & keepalive_intvl 可以配置,但 tcp_keepalive_probes 不能改变。默认情况下,当 TCP 套接字初始化时,将保持连接超时设置为 2 小时,保持连接间隔为 1 秒。保持活动超时的默认系统范围值可通过 KeepAliveTime 注册表设置进行控制,该设置以毫秒为单位。
On Windows Vista and later, the number of keep-alive probes (data retransmissions) is set to 10 and cannot be changed.
在 Windows Vista 和更高版本上,保持活动探测(数据重新传输)的数量设置为 10,并且无法更改。
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.
在Windows Server 2003、Windows XP和Windows 2000上,keep-alive探测器的数量默认设置为5。keep-alive探测器的数量是可控的。对于 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 );
int WSAIoctl( SocketFD, // 标识套接字的描述符 SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // 指向 tcp_keepalive struct (DWORD) cbInBuffer 的指针, // 输入缓冲区的长度 NULL, // 输出缓冲区 0, // 的大小输出缓冲区 (LPDWORD) lpcbBytesReturned, // 返回的字节数 NULL, // OVERLAPPED 结构 NULL // 完成例程 );
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.
Linux 内置了对 keepalive 的支持,需要启用 TCP/IP 网络才能使用它。程序必须使用setsockopt 接口为其套接字请求keepalive 控制。
int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
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.
每个客户端套接字都将使用 java.net.Socket 创建。每个套接字的文件描述符 ID 将使用 java 反射检索。