Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在此处正确关闭ssh连接/会话?_Java_Ssh_Client Server - Fatal编程技术网

Java 如何在此处正确关闭ssh连接/会话?

Java 如何在此处正确关闭ssh连接/会话?,java,ssh,client-server,Java,Ssh,Client Server,我有一个客户机/服务器套接字程序。 服务器部分通过ssh连接到主机,运行脚本,并将每一行输出发送到客户端 下面的服务器代码部分返回一个包含脚本输出的BufferedReader: public synchronized BufferedReader runScript(<params>) { BufferedReader br = null ; try { Connection conn = new Connection(host); conn

我有一个客户机/服务器套接字程序。 服务器部分通过ssh连接到主机,运行脚本,并将每一行输出发送到客户端

下面的服务器代码部分返回一个包含脚本输出的
BufferedReader

public synchronized BufferedReader runScript(<params>) {    
  BufferedReader br = null ;
  try {
      Connection conn = new Connection(host);
      conn.connect();
      ... // authentication part
      Session sess = conn.openSession();
      sess.execCommand("ascript");
      InputStream stdout = new StreamGobbler(sess.getStdout());
      br = new BufferedReader(new InputStreamReader(stdout));
  } catch (Exception e) {
      e.printStackTrace();
  }
  return br;
}
public synchronized BufferedReader runScript(){
BufferedReader br=null;
试一试{
连接连接=新连接(主机);
连接();
…//身份验证部分
会话sess=conn.openSession();
sess.execCommand(“ascript”);
InputStream stdout=new StreamGobbler(sess.getStdout());
br=新的BufferedReader(新的InputStreamReader(stdout));
}捕获(例外e){
e、 printStackTrace();
}
返回br;
}
上面的方法是从另一个服务器端类/代码调用的,如下所示,通过套接字将BufferedReader的每一行写入客户端,以便客户端在脚本运行时看到脚本的实时输出:

BufferedReader br = new UnixCommandExecutor().runScript(<params>);
String line;
while ((line = br.readLine()) != null) {
      out.writeObject(line);
}
BufferedReader br=new UnixCommandExecutor().runScript();
弦线;
而((line=br.readLine())!=null){
out.writeObject(行);
}
runScript方法的明显问题是它不会关闭ssh连接和会话(ganymed ssh lib),因为它会在底层脚本仍然运行时立即返回BufferedReader(如果我没有弄错的话)。如果我在return语句之前关闭这些,则BufferedReader将不完整。 那么,在底层脚本完成后,如何在此处正确关闭连接/会话


(我知道try with resources并将使用它,但我怀疑它能否完全解决问题?

我建议您重构代码,以便

  • 将零件包装到对象中,然后处理关闭操作
  • 或者,您可以立即使用读卡器,并在使用完毕后关闭连接
在未保持连接的情况下,不要将读卡器传递到外部

下面是一个稍微简化的示例,说明如何实现

如果在使用读取器之前需要处理多个步骤,则可能无法将ResultHandler包装在try{…}catch块中。在这种情况下,你需要一种不同的方法来确保这最终会被关闭

但从你对问题的描述来看,情况可能并非如此

如果您不希望在操作完成之前阻止(无论如何,此操作应该在后台线程中执行),那么您可能希望将收到的每个输出行发送到可以显示它的位置。在这种情况下,您应该提供一个用于转发接收到的线路的接口

当读卡器仍然接收输出时(只要输入流/连接处于活动状态),您可能需要循环。不知何故,你需要弄清楚你的操作何时完成

例如,脚本可以在连接完成后(从服务器端)关闭连接,或者返回特定于您的内容,您可以将其解释为操作结束

公共类ResultHandler{
字符串主机;
连接接头;
BufferedReader reader=null;
公共结果处理程序(字符串主机){
this.host=host;
}
public void connect()引发异常{
//如果您打算重用该对象,只需检查之前是否已正确清理
close();
conn=新连接(主机);
连接();
…//身份验证部分
//您可能希望将实际处理移到其他方法
会话sess=conn.openSession();
sess.execCommand(“ascript”);
InputStream stdout=new StreamGobbler(sess.getStdout());
br=新的BufferedReader(新的InputStreamReader(stdout));
}
公共BufferedReader getReader(){
返回此.reader;
}
公众假期结束(){
If(读卡器!=null){
reader.close();
}
如果(conn!=null){
康涅狄格州关闭();
}
}
公共图书馆{
close();
}
}
已同步的void runScript(){
ResultHandler处理器;
试一试{
handler=新的ResultHandler(主机);
connect();
//无论你需要做什么,都要消耗读者
}捕获(例外e){
e、 printStackTrace();
}最后{
//或者使用try with resource并为此实现适当的接口
if(处理程序!=null){
handler.close();
}
}
}

您需要告诉我们您正在使用的众多SSH api中的哪一个,但是其中肯定有一个
close()
方法吗?@user207421我已经提到了api(ganymed),是的,其中当然有一个
close()
方法。这不是问题的重点,这里的实际问题是,在命令完成之后,也就是在您消耗了它的所有输出之后,我应该把close()放在哪里。很明显,那显然是在哪里?除了
runScript()
方法之外?非常感谢您的建议。我不想立即使用阅读器,因为这会在客户端显示脚本输出时消除“实时效果”。我认为,将不同的部分包装成一个自定义对象是一种可行的方法。