【问题标题】:java.net.Socket TCP keep-alive usagejava.net.Socket TCP keep-alive 用法
【发布时间】:2019-08-07 02:21:07
【问题描述】:

如何使用java.net.Socket setKeepAlive(boolean b) API?

我正在使用Socket 托管一个简单的服务器。 客户端可以连接和发送数据。除非客户端发送流结束,否则我不会关闭连接。客户端可以继续保持连接任意时间。数据传输将继续进行,但突然间我发现连接丢失,没有任何日志。一旦客户端(不是服务器)重新启动,传输就会重新开始。 我没有设置任何timeout,因为默认情况下它是无穷大的。我想了解setKeepAlive 的实际作用,以便我能够决定是否需要将其设置为true。 有人可以帮我理解吗?谢谢。

【问题讨论】:

  • 也许你能澄清一下到底是什么问题?并且可能发布给你带来麻烦的代码。
  • 如果您不了解setKeepAlive() 的作用,那么您怎么知道它解决了您的问题?
  • 嗨,我编辑了我的问题。

标签: java sockets


【解决方案1】:

正如setKeepAlive() 的文档所述,它将启用(或禁用)套接字上的SO_KEEPALIVE 选项。

如果为 TCP 套接字设置了 keepalive 选项,并且 2 小时内没有通过套接字在任一方向交换数据(注意:实际值取决于实现),TCP 会自动向对等方发送 keepalive 探测。此探测是对等方必须响应的 TCP 段。期望三个响应之一: 1. 对等点以期望的 ACK 响应。不通知应用程序(因为一切正常)。 TCP 将在另外 2 小时不活动后发送另一个探测。 2. 对端响应一个 RST,它告诉本地 TCP 对端主机已经崩溃并重新启动。插座已关闭。 3. 对端无响应。插座已关闭。此选项的目的是检测对等主机是否崩溃。仅对 TCP 套接字有效:SocketImpl

Here 是解释SO_KEEPALIVE 选项的另一个参考。


请注意,在网络中,连接可能随时因各种原因而丢失。如果连接经过 NAT 路由器,NAT 表中的条目可能会过期(当连接空闲时)并且连接会因此而丢失。客户端可能停止运行,或被暂停(尤其是笔记本电脑和移动设备),或电缆可能断开,或 WiFi(或蜂窝)信号可能受到干扰,或者......列表可以继续。需要编写您的服务器以优雅地应对连接丢失。

【讨论】:

  • 您好,感谢您的解释。但是如何在我的应用程序中编写代码来检查客户端是否处于活动状态等?
  • @LPD 要检查客户端是否处于活动状态,需要您的应用程序协议发送消息并期待响应。通常,无法知道 TCP 连接的远端是否“活动”。该程序可能暂时不需要发送任何内容,或者它可能已经消失(软件退出、硬件死机、断电、反铲断网线等等)。
  • 这不是强制性的。您需要决定您的协议是否合适。
  • 文档不正确。套接字未关闭。该应用程序仍然必须关闭它。 connectionreset, 并且对它的下一个 I/O 操作将抛出一个IOException
【解决方案2】:

我遇到了类似的问题

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

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

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

在 Windows Vista 及更高版本上,keep-alive 探测(数据重新传输)的数量设置为 10 且无法更改。

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

int WSAIoctl( SocketFD, // 标识套接字的描述符 SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // 指向 tcp_keepalive 结构的指针 (DWORD) cbInBuffer, // 输入缓冲区的长度 NULL, // 输出缓冲区 0, // 输出缓冲区大小 (LPDWORD) lpcbBytesReturned, // 返回的字节数 NULL, // 重叠结构 NULL // 完成例程 );

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 反射检索。

【讨论】:

  • 请不要在多个旧问题中继续发布相同的答案。如果您认为它们是重复的,请标记为重复。
猜你喜欢
  • 2016-09-07
  • 2013-03-25
  • 1970-01-01
  • 2014-07-25
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多