使用jsch进行sftp传输时遇到的问题com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset

在做某个业务时,需要将文件传输到另一台服务器,指定使用sftp方式;于是在网上找到jsch包使用,原先代码大致如下:

1 ChannelSftp channelSftp = null; 2 try { 3 JSch jsch = new JSch(); 4 jsch.getSession("ftpUserName", "ftpHost", 22); 5 Session sshSession = jsch.getSession("ftpUserName", "ftpHost", 22); 6 System.out.println("Session created."); 7 sshSession.setPassword("ftpPassword"); 8 Properties sshConfig = new Properties(); 9 sshConfig.put("StrictHostKeyChecking", "no"); 10 sshSession.setConfig(sshConfig); 11 sshSession.connect(); 12 System.out.println("Session connected."); 13 System.out.println("Opening Channel."); 14 Channel channel = sshSession.openChannel("sftp"); 15 channel.connect(); 16 channelSftp = (ChannelSftp) channel; 17 18 //todo 上传文件 19 } catch (Exception e) { 20 //todo 异常处理 21 } finally { 22 //断开sftp连接 23 if (channelSftp != null) { 24 channelSftp.disconnect(); 25 } 26 }

程序运行后大约过了几天,发现日志产生大量连接异常的日志,主要是两类异常:SocketException和NoRouteToHostException

com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset at com.jcraft.jsch.Session.connect(Session.java:534) at com.jcraft.jsch.Session.connect(Session.java:162) at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)



com.jcraft.jsch.JSchException: java.net.NoRouteToHostException: Cannot assign requested address (Address not available) at com.jcraft.jsch.Util.createSocket(Util.java:344) at com.jcraft.jsch.Session.connect(Session.java:194) at com.jcraft.jsch.Session.connect(Session.java:162) at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.net.NoRouteToHostException: Cannot assign requested address (Address not available) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at java.net.Socket.<init>(Socket.java:434) at java.net.Socket.<init>(Socket.java:211) at com.jcraft.jsch.Util.createSocket(Util.java:338) ... 17 common frames omitted
 

首先我百度了下,找到有人提到修改socket连接的配置,于是我尝试修改:

1. 修改端口释放后的等待时间为30s。echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

2. 修改/proc/sys/net/ipv4/tcp_tw_reuse为1。echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

3. 修改/proc/sys/net/ipv4/tcp_tw_recycle为1。echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

4.增加可用端口  vim /etc/sysctl.conf 

net.ipv4.ip_local_port_range = 10000     65000      -----意味着10000~65000端口可用 

改完后,执行命令“sysctl -p”使参数生效。

 

修改配置后,重启程序,发现过了一天,仍然出现上述的问题;继续百度查看,发现有人提到连接关闭的问题,于是查了下服务器的ssh连接数

netstat |grep ssh |wc -l

这一查,发现有5500多个连接未关闭(随着时间推移,空闲连接会自动关闭),于是问题的原因大致定位到了:程序生成连接的速度大于连接释放的速度;但是问题的根源还是在于,程序没有正确关闭连接。

不仅仅要断开channel,还要断开session。修改后的代码如下:

1 ChannelSftp channelSftp = null; 2 try { 3 JSch jsch = new JSch(); 4 jsch.getSession("ftpUserName", "ftpHost", 22); 5 Session sshSession = jsch.getSession("ftpUserName", "ftpHost", 22); 6 System.out.println("Session created."); 7 sshSession.setPassword("ftpPassword"); 8 Properties sshConfig = new Properties(); 9 sshConfig.put("StrictHostKeyChecking", "no"); 10 sshSession.setConfig(sshConfig); 11 sshSession.connect(); 12 System.out.println("Session connected."); 13 System.out.println("Opening Channel."); 14 Channel channel = sshSession.openChannel("sftp"); 15 channel.connect(); 16 channelSftp = (ChannelSftp) channel; 17 18 //todo 上传文件 19 } catch (Exception e) { 20 //todo 异常处理 21 } finally { 22 //断开sftp连接 23 if (channelSftp != null) { 24 try { 25 channelSftp.disconnect(); 26 //关闭会话 27 Session session = channelSftp.getSession(); 28 if (session != null) { 29 session.disconnect(); 30 } 31 } catch (Exception e) { 32 //todo 异常处理 33 } 34 } 35 }

重新运行,观察ssh连接数,发现恢复正常,每次文件传输完毕后,会话及时结束。


__EOF__

本文作者yjry
本文链接https://www.cnblogs.com/yjry-th/p/16470795.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   yjry-th  阅读(9099)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示