本文主要是介绍Apache MINA SSHD,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1.远程登录
1.1密码登录
1.2密钥登录
2.执行命令
2.1 ChannelExec
2.2 ChannelShell
3.文件传输
3.1 上传文件
3.2 下载文件
3.3 SftpFileSystem
Apache MINA SSHD(Secure Shell Daemon)是基于Apache MINA(Multipurpose Infrastructure for Network Applications)开发的一个开源的Java库,专门用于提供SSH(Secure Shell)服务。SSH是一种网络协议,用于在不安全的网络环境中进行安全通信和远程操作:主要用于远程登录、文件传输、以及安全的命令执行等场景。
1.远程登录
1.1密码登录
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Sshd工具类*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
1.2密钥登录
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Sshd工具类*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
2.执行命令
2.1 ChannelExec
ChannelExec是Apache Mina SSHD中的一个类,它提供了一种在SSH连接上执行远程命令的方式,以及处理命令输入、输出、参数和状态的能力。它灵活性高、可扩展性强,适用于需要与远程服务器进行命令交互和执行的场景。
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Sshd工具类*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {SshdTest sshUtil = new SshdTest("192.168.179.131",22,"weisx","123456");sshUtil.execCommand("pwd");}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 执行命令* @param command* @return*/public String execCommand(String command){session.resetAuthTimeout();System.out.println("exe cmd: "+ command);// 返回结果流ByteArrayOutputStream out = new ByteArrayOutputStream();// 错误信息ByteArrayOutputStream err = new ByteArrayOutputStream();try(ChannelExec channelExec = session.createExecChannel(command)) {channelExec.setOut(out);channelExec.setErr(err);// 执行并等待channelExec.open();Set<ClientChannelEvent> events =channelExec.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),TimeUnit.SECONDS.toMillis(100000));// 检查请求是否超时if (events.contains(ClientChannelEvent.TIMEOUT)) {throw new RuntimeException("请求连接超时");}// 一般退出状态为0表示正常int exitStatus = channelExec.getExitStatus();if (exitStatus == 1) {log.info("exitStatus:{}",exitStatus);
// throw new RuntimeException("执行命令失败:"+exitStatus);}} catch (Exception e) {throw new RuntimeException(e);}return out.toString().trim();}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
2.2 ChannelShell
ChannelShell是Apache Mina SSHD中的一个用于使用交互式shell的类,它提供了在远程服务器上执行交互式命令和脚本,并与其进行实时交互的功能。与 ChannelExec 相比,可以更灵活地与远程服务器进行交互和执行复杂的命令。
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Sshd工具类*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {SshdTest sshUtil = new SshdTest("192.168.179.131",22,"weisx","123456");String[] commends ={"pwd","cd ","pwd"};sshUtil.execCommand(commends);}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 执行命令* @param commands* @return*/public String execCommand(String[] commands){session.resetAuthTimeout();System.out.println("exe cmd: "+ String.join(";",commands));// 命令返回的结果StringBuffer resultBuf = new StringBuffer("");try (ChannelShell channel = session.createShellChannel()) {channel.open().verify(5 , TimeUnit.SECONDS);// 执行命令try (PrintStream out = new PrintStream(channel.getInvertedIn())) {for (String command:commands){out.println(command);out.flush();}out.println("exit");out.flush();}//channel.waitFor(Collections.singleton(ClientChannelEvent.CLOSED), 0);try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(channel.getInvertedOut()))) {String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);resultBuf.append(line);}}} catch (IOException e) {throw new RuntimeException(e);}return resultBuf.toString().trim();}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
3.文件传输
SftpClient是基于Apache MINA SSHD库的一个SFTP(SSH File Transfer Protocol)客户端实现,它提供了一套方便且易于使用的API,用于在Java应用程序中与远程SFTP服务器进行文件传输和管理。
3.1 上传文件
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;
import org.apache.sshd.sftp.client.fs.SftpPath;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Sshd工具类** https://github.com/apache/mina-sshd/blob/master/docs/sftp.md*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {SshdTest sshUtil = new SshdTest("192.168.179.131",22,"weisx","123456");sshUtil.uploadFile(new File("F:\\24\\tmp.txt"),"/home/weisx/");}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 上传文件* @param uploadFile 上传的文件* @param remotePath 远程目录*/public String uploadFile(File uploadFile,String remotePath) {try(SftpClient sftpClient = SftpClientFactory.instance().createSftpClient(session);OutputStream outputStream = sftpClient.write(remotePath)) {Files.copy(uploadFile.toPath(), outputStream);return remotePath;} catch (IOException e) {throw new RuntimeException(e);}}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
3.2 下载文件
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;
import org.apache.sshd.sftp.client.fs.SftpPath;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Sshd工具类** https://github.com/apache/mina-sshd/blob/master/docs/sftp.md*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {SshdTest sshUtil = new SshdTest("192.168.179.131",22,"weisx","123456");sshUtil.downloadFile("/home/weisx/tmp.txt","F:\\24\\");}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 下载文件* @param remoteFilePath 下载的文件* @param savePath 保存的目录*/public void downloadFile(String remoteFilePath,String savePath) {try(SftpClient sftpClient = SftpClientFactory.instance().createSftpClient(session);InputStream inputStream = sftpClient.read(remoteFilePath)) {File destFile = new File(savePath);Files.copy(inputStream , destFile.toPath() , StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {throw new RuntimeException(e);}}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
3.3 SftpFileSystem
SftpFileSystem是Apache Mina SSHD中实现的基于VFS框架的SFTP文件系统,它供了一套统一的API和一些额外的高级功能,方便用户访问和操作远程文件系统,适用于复杂的文件系统操作和要求更高级功能的场景。
package com.yichenkeji.starter.ssh;import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;
import org.apache.sshd.sftp.client.fs.SftpPath;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Sshd工具类** https://github.com/apache/mina-sshd/blob/master/docs/sftp.md*/
@Slf4j
public class SshdTest {private SshClient client;private ClientSession session;public static void main(String[] args) throws Exception {SshdTest sshUtil = new SshdTest("192.168.179.131",22,"weisx","123456");sshUtil.fileMeta("/home/weisx/tmp.txt");}/*** 连接* @param host* @param port* @param username*/private void connect(String host, int port, String username) {client = SshClient.setUpDefaultClient();client.start();try {session = client.connect(username, host, port).verify(5000).getSession();} catch (IOException e) {throw new RuntimeException(e);}}/*** 密码登录* @param host* @param port* @param username* @param password*/public SshdTest(String host, int port, String username, String password) {connect(host,port,username);try {session.addPasswordIdentity(password); // for password-based authenticationif (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (IOException e) {throw new RuntimeException(e);}}/*** 密钥登录* @param host* @param port* @param username*/public SshdTest(String host, int port, String username) {connect(host,port,username);try {String privateKeyPath = System.getProperty("user.home") + "/.ssh/id_rsa";String privateKeyContent = new String(Files.readAllBytes(Paths.get(privateKeyPath)));//获取密钥对KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");KeyPair keyPair = rsa.generateKeyPair();ByteArrayOutputStream stream = new ByteArrayOutputStream();stream.write(privateKeyContent.getBytes());ObjectOutputStream o = new ObjectOutputStream(stream);o.writeObject(keyPair);session.addPublicKeyIdentity(keyPair);if (session.auth().verify(5000).isFailure()) {throw new RuntimeException("验证失败");}} catch (Exception e) {throw new RuntimeException(e);}}/*** 获取文件信息* @param filePath 文件路径*/public void fileMeta(String filePath) {try(SftpFileSystem sftp = SftpClientFactory.instance().createSftpFileSystem(session)) {SftpPath path = sftp.getPath(filePath);System.out.println("文件名:" + path.getFileName());System.out.println("文件大小:" + Files.size(path));System.out.println("最后更新时间:" + Files.getLastModifiedTime(path));//如果是目录,则可以列出目录下全部文件try (Stream<Path> stream = Files.list(path)) {List<Path> paths = stream.collect(Collectors.toList());for (Path p : paths) {if (Files.isDirectory(p)) {System.out.println("文件夹:" + p.getFileName());} else {System.out.println("文件: " + p.getFileName());}}}} catch (IOException e) {throw new RuntimeException(e);}}/*** 关闭连接*/public void close(){log.info("关闭 SSH");closeSession();if(client != null){try {client.close();} catch (IOException e) {log.error(e.getMessage());}}}private void closeSession() {if(session != null){try {session.close();} catch (IOException e) {log.error(e.getMessage());}}}
}
这篇关于Apache MINA SSHD的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!