【问题标题】:Issue with buffer when using jsch使用 jsch 时出现缓冲区问题
【发布时间】:2014-10-30 02:15:18
【问题描述】:

我目前在实现 jsch 库以从 ZyXel 开关获取信息时遇到问题。程序本身会抓取一些信息来确认交换机的类型,然后上传正确的固件和配置。

对我来说,我的问题似乎是缓冲区问题。我发送命令没有问题,但是当我发送它时,取决于我运行它的时间或频率,我要么得到我应该得到的一半信息,要么得到全部信息。我认为这是因为有时缓冲区不会一直清空到 ByteArrayInputStream 中,但此时我不知所措。我想知道是否有人可以指出我出错的正确方向。我认为这是一个基本的 InputStream 或 jsch 文档问题误解

谢谢!..我的代码如下。

package ssh;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.jcraft.jsch.*;

public class ssh {
    private static String user = "admin";
    private static String host = "192.168.1.1";
    private static String password = "1234";
    private static  String command = "";
    public static void startAutomation() {  
        JSch jsch = new JSch();
        Session session = null;
        OutputStream output = null;
        Channel channel = null;
        try {

            session = jsch.getSession(user,host,22);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking","no");

            session.connect();
            channel = session.openChannel("shell");

            command = "show system-information\n";

            output = runCommand(command, session, channel);
            String test = "NOTHING";
            if (output.toString().contains("ES-2024A")) {
                test = "true";
                command = "show run\n";
                output = runCommand(command,session,channel);
            } else {
                test = "false";
            } 
            System.out.println(test + " This is a 2024A");

        } catch (JSchException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  finally {
            channel.disconnect();
            session.disconnect();
        }
    }

public static OutputStream runCommand(String c,Session session,Channel channel) throws InterruptedException, JSchException{
    InputStream is = new ByteArrayInputStream(c.getBytes());
    channel.setInputStream(is);

    OutputStream outputInfo = new ByteArrayOutputStream();
    channel.setOutputStream(outputInfo);

    channel.connect(15*1000);

    try {
        is.close();
        outputInfo.flush();
        outputInfo.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return outputInfo;
}

}

【问题讨论】:

    标签: java jsch


    【解决方案1】:

    我正在从事类似的项目,现在我创建了不需要等待任何东西的全局输出流。 我重写了 OutputStream 以使用 JTextArea 作为输出

    private java.util.List<Character> buffer = new ArrayList<Character>();
    public class AreaOutputStream extends OutputStream {
    private JTextArea textArea;
    
    public AreaOutputStream(JTextArea textArea) {
        this.textArea = textArea;
    }
    
    @Override
    public synchronized void write(int b) throws IOException {
        // collect all character into the buffer
        buffer.add((char) 
        // on '\n' character append to output window
        if (String.valueOf((char) b).equals("\n")) {
                StringBuilder sb = new StringBuilder(buffer.size());
                for (Character c : buffer) sb.append(c);
                String line = sb.toString();
                // filter output from special characters
                //and replace invitation '[username@server~]$ ' with current time
                line = line.replaceAll(" \r", "");
                line = line.replaceAll("\r", "");
                line = line.replaceAll(String.valueOf(Pattern.compile("\\[[0-9][^m ]*m")), "");
                line = line.replaceAll(String.valueOf(Pattern.compile("\\[.*@[^$]*\\$ ")), DateFormat.getTimeInstance().format(java.lang.System.currentTimeMillis()) + " ");
                line = line.replaceAll(String.valueOf(Pattern.compile("\u001B")), "");
                if (!line.matches("(.*)Last login(.*)from(.*)\n")) {
                    textArea.append(line);
                    textArea.setCaretPosition(textArea.getDocument().getLength());
                }
            buffer.clear();
        }
    
    }
    }
    

    因此,要在您创建频道的部分中使用此输出流,请设置以下内容:

    channel.setOutputStream(new AreaOutputStream(TEXT_AREA_NAME))
    

    因此,您可以创建另一个通道来执行命令并将此类设置为输出 - 所有这些都将出现在 JTextArea 中。

    顺便说一句,现在我尝试创建 InputStream 以在一个通道中发送命令(联系方式请将“domain.name”替换为“mail.ru”)

    希望这对我的英语有所帮助和抱歉。

    【讨论】:

      猜你喜欢
      • 2014-06-14
      • 2017-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多