移动端SSHD服务器向JSch客户端传文件遇连接重置问题求助
问题:安卓模拟器JSch客户端连接手机SSHD服务器时出现连接重置
手机上运行的SSHD服务器无报错,但安卓模拟器里的JSch客户端尝试从手机内部存储下载文件时,抛出Connection reset错误。已添加网络权限和相关依赖,问题仍未解决。
客户端代码
public void startClient(){ String localFile = "/data/user/0/com.open.jsch/databases/au.au_1"; String remoteFile = "/data/user/0/com.open.androidsshd/databases/au.au_1"; Session jschSession = null; try { JSch jsch = new JSch(); jsch.setKnownHosts("/home/mkyong/.ssh/known_hosts"); jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT); // authenticate using private key // jsch.addIdentity("/home/mkyong/.ssh/id_rsa"); // authenticate using password jschSession.setPassword(PASSWORD); //Missing code java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); jschSession.setConfig(config); // System.out.println("Establishing connection"); // 10 seconds session timeout jschSession.connect(SESSION_TIMEOUT); Channel sftp = jschSession.openChannel("sftp"); // 5 seconds timeout sftp.connect(CHANNEL_TIMEOUT); ChannelSftp channelSftp = (ChannelSftp) sftp; // transfer file from local to remote server //channelSftp.put(localFile, remoteFile); // download file from remote server to local channelSftp.get(remoteFile, localFile); System.out.println("got the file"); channelSftp.exit(); } catch (JSchException | SftpException e) { e.printStackTrace(); } finally { if (jschSession != null) { jschSession.disconnect(); } } }
客户端错误日志
2022-10-30 21:55:59.228 15159-15202/com.allah.jsch W/System.err: com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset 2022-10-30 21:55:59.228 15159-15202/com.allah.jsch W/System.err: at com.jcraft.jsch.Session.connect(Session.java:565) 2022-10-30 21:55:59.228 15159-15202/com.allah.jsch W/System.err: at com.allah.jsch.Client.startClient(Client.java:71) 2022-10-30 21:55:59.228 15159-15202/com.allah.jsch W/System.err: at com.allah.jsch.MainActivity$2.run(MainActivity.java:78) 2022-10-30 21:55:59.229 15159-15202/com.allah.jsch W/System.err: at java.lang.Thread.run(Thread.java:764)
服务器代码
int port = 8888; SshServer sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider( "src/test/resources/hostkey.ser")); sshd.setSubsystemFactories(Arrays .<NamedFactory<Command>>asList(new SftpSubsystem.Factory())); sshd.setCommandFactory(new ScpCommandFactory()); sshd.setShellFactory(new EchoShellFactory()); // necessary if you want to type commands over ssh sshd.setPasswordAuthenticator(new PasswordAuthenticator() { @Override public boolean authenticate(String u, String p, ServerSession s) { return ("sftptest".equals(u) && "sftptest".equals(p)); } }); try { sshd.start(); } catch (IOException e) { e.printStackTrace(); }
权限配置
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
客户端Gradle依赖
// https://mvnrepository.com/artifact/org.apache.sshd/sshd-core implementation group: 'org.apache.sshd', name: 'sshd-core', version: '0.6.0' // https://mvnrepository.com/artifact/org.slf4j/slf4j-simple testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.6.2' // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16 implementation group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46' implementation files('libs\\jsch-0.1.55.jar')
可行解决方案
1. 修正模拟器与真机的网络连通性
安卓模拟器无法直接用localhost访问物理真机,需:
- 将客户端
REMOTE_HOST设置为真机的局域网IP(可通过手机WiFi设置查看) - 确保真机和模拟器连接同一WiFi网络
- 若使用Android Studio模拟器,物理真机需用自身局域网IP,而非
10.0.2.2(该地址仅映射到模拟器宿主机)
2. 修复服务器HostKey存储路径
服务器代码中src/test/resources/hostkey.ser是桌面环境路径,安卓真机无法识别,需改为应用内部存储路径:
// 获取应用内部存储目录 String hostKeyPath = getFilesDir().getAbsolutePath() + "/hostkey.ser"; sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKeyPath));
HostKey生成失败会直接导致SSH握手中断,触发连接重置。
3. 解决依赖冲突
客户端同时引入sshd-core和JSch两个SSH客户端实现,存在版本冲突,移除sshd-core相关依赖:
// 移除冲突依赖 // implementation group: 'org.apache.sshd', name: 'sshd-core', version: '0.6.0' // testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.6.2' // 保留必要依赖 implementation group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46' implementation files('libs\\jsch-0.1.55.jar')
4. 移除客户端无效的KnownHosts配置
客户端代码中/home/mkyong/.ssh/known_hosts是Linux桌面路径,安卓模拟器不存在,直接注释:
// jsch.setKnownHosts("/home/mkyong/.ssh/known_hosts");
已设置StrictHostKeyChecking=no,无需该文件。
5. 验证服务器端口可用性
- 在真机上用
netstat命令检查8888端口是否被占用 - 关闭真机防火墙(若有),确保允许8888端口的TCP连接
- 用电脑SSH工具连接真机IP+8888端口,验证服务器是否正常响应
6. 延长超时时间并增加调试日志
延长客户端连接超时,避免网络延迟导致重置:
// 会话超时改为30秒 jschSession.connect(30000); Channel sftp = jschSession.openChannel("sftp"); // 通道超时改为10秒 sftp.connect(10000);
服务器添加会话监听日志,确认是否收到连接请求:
sshd.setSessionListener(new SessionListener() { @Override public void sessionCreated(ServerSession session) { Log.d("SSHD", "收到新连接:" + session.getIoSession().getRemoteAddress()); } @Override public void sessionEvent(ServerSession session, Event event) {} @Override public void sessionClosed(ServerSession session) {} });
内容的提问来源于stack exchange,提问作者CodeBlack
相关产品推荐
相关产品推荐

