5

我正在使用 SSH Ganymed 库别名 Trilead 别名 Orion。

我试图了解会话的确切行为,因为我需要保持 ssh 连接打开很长时间(可能永远)并在我的 jvm 出现故障或类似情况时关闭它。

所以,我的问题是这个。假设我做这样的事情:

Connection conn = new Connection(this.hostName, this.port);
conn.addConnectionMonitor(new ConnectionMonitor()
{            
  @Override
  public void connectionLost(Throwable reason)
  {
     System.out.println("Connection Lost "   reason.getMessage());
  }
});
conn.connect(null, 1000, 20000);
conn.authenticateWithPublicKey(this.user, keyfile, this.password);
Thread.sleep(30000); //sleep the Thread for 30 seconds
Session sess = conn.openSession();
sess.execCommand("ls");
conn.close();

而且,在线程休眠的那 30 秒内,我断开网络接口以模拟网络问题。

1)connectionMonitor没有拦截到disconnect事件并且没有打印Connection Lost消息 2)当

Session sess = conn.openSession();

被执行,进程阻塞并且没有任何反应,直到我不再连接网络接口。这是因为,查看 Ganymed 代码,似乎由于未检测到断开连接事件,会话已打开,并且在会话成功之前打开了一个锁。

所以我的问题是:1)这种行为是想要的还是一个错误?2)有没有办法在 Connection.openSession() 方法和 Connection.connect() 方法中设置超时?

提前致谢。

4

1 回答 1

3

我认为问题在于您无法通过拔下电缆 30 秒来模拟 ssh 断开连接。看看这个:如果您在终端上打开 ssh 连接并拔下电缆,ssh 客户端也会阻塞,但在再次插入电缆后会自动重新连接。我假设您的代码也会这样做。

如果在配置的时间内(即一段时间不活动),无论是否插入电缆,客户端和服务器之间都没有发送数据,您通常会断开连接。默认情况下,此时间段很可能大于 30 秒。

在 sshd 服务器上,您可以配置

ClientAliveInterval

TCPKeepAlive

ClientAliveCountMax

这些参数将决定服务器在从客户端收到一些数据之前要等待多长时间,以及他多久会接受一个简单的保活数据包而不是真实数据。在客户端你可以配置

ServerAliveInterval

如果 ClientAliveInterval 小于 ServerAliveInterval - 服务器期望保持活动数据包的频率高于客户端发送它们的频率 - 在 ClientAliveInterval 不活动量后您将断开连接。有了它,您可以测试您的代码。

这些配置也是保持 ssh 连接无限期打开的关键。如果您的 ServerAliveInterval 小于 ClientAliveInterval - 客户端将比服务器期望的更频繁地发送保持活动数据包 - 您的连接将无限期打开。

看看这里https://www.simplified.guide/ssh/disable-timeout

我认为重新启动服务器或客户端计算机仍会导致断开连接。如果您的客户端计算机重新启动,无论如何您都需要再次运行整个代码,如果服务器计算机重新启动,连接监视器将启动并重新连接。

于 2013-01-05T01:05:15.190 回答