gpt4 book ai didi

Java RMI 在租约到期后不关闭套接字

转载 作者:行者123 更新时间:2023-12-01 06:00:31 27 4
gpt4 key购买 nike

我启用 RMI 的应用程序似乎正在泄漏套接字。我有一个通过 RMI 提供服务的 Java 应用程序。它使用在 Linux 上运行的 Java SE 1.6 RMI 实现。我观察到的问题是,如果客户端使用注册表获取对我的远程对象的引用,然后连接突然断开(断电、电缆拔出等...),服务器将保持套接字打开。我希望 RMI 实现能够在客户端的租约到期后进行清理,但这并没有发生。在服务器上,当租约到期时,将调用我的远程对象的 unreferenced() 方法,但套接字在 netstat 中无限期地保持可见,处于“ESTABLISHED”状态。

由于我们无法强制客户端执行任何特定行为,几天后,我们的 Linux 发行版中的打开文件描述符达到了默认限制 1024,导致服务器无法打开任何新套接字或文件。我考虑过 TCP keepalive,但由于 RMI 抽象了网络层,因此在建立连接后我无法访问实际的服务器套接字。

有没有办法强制 RMI 层清理与租约过期的客户端连接相关的套接字?

更新:我使用的解决方案与所选答案类似,但使用不同的方法。我使用了一个自定义套接字工厂,然后将 createServerSocket() 返回的 ServerSocket 实例包装在一个透明包装器中,该包装器传递除accept() 之外的所有方法。在 accpet 方法中,在返回套接字之前启用 keepalive。

public class KeepaliveSocketWrapper extends ServerSocket
{
private ServerSocket _delegate = null;
public KeepaliveSocketWrapper(ServerSocket delegate)
{
this._delegate = delegate;
}

public Socket accept() throws IOException
{
Socket s = _delegate.accept();
s.setKeepAlive(true);
return s;
}
.
.
.
}

最佳答案

public class MySocketFactorySettingKeepAlive ... {
// overwrite createSocket methods, call super.createSocket, add keepAlive
}

Socket.setSocketImplFactory(youFactoryDemandingKeepAlive);

然后就使用 RMI 即可。

如果我没记错的话,诀窍是在系统打开第一个套接字之前设法设置工厂——Java 不允许覆盖工厂;在最坏的情况下,使用反射来覆盖它:)))(开玩笑;将是一个黑客)

此外,您可能需要允许 SecurityManager 中的特定操作。

关于Java RMI 在租约到期后不关闭套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/227276/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com