关于sftp连接的问题.
关于sftp连接的问题.2011-09-08 12:55最近在window环境下弄了下sftp,用java代码写客户端的时候连接总是出问题.大家帮忙看下啊.;
服务器端是配置在本地,上面是本地服务器的配置.
验证方式设置为密码验证,兼容密钥验证,为了简化程序下面使用的是密码验证.
用户名:userhash.
密码:1991
客户端代码是用jsch jar包工具实现.
代码如下:
package com.zj.sftp;
/*
* Created on 2011-9-7
* Copyright 2011 by zj
*
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
import java.util.Vector;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;
/**
* @author zhangjing
*/
public class MySFTP {
public static final UserInfo defaultUserInfo = new UserInfo() {
public String getPassphrase() {
return null;
}
public String getPassword() {
return null;
}
public boolean promptPassword(String arg0) {
return false;
}
public boolean promptPassphrase(String arg0) {
return false;
}
public boolean promptYesNo(String arg0) {
return true;
}
public void showMessage(String arg0) {
}
};
/**
* 连接sftp服务器
*
* @param host
* 主机
* @param port
* 端口
* @param username
* 用户名
* @param password
* 密码
* @return
*/
public ChannelSftp connect(String host, int port, String username,
String password) {
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
Session sshSession = jsch.getSession(username, host, port);
System.out.println("Session created.");
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
System.out.println("Session connected.");
System.out.println("Opening Channel.");
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
System.out.println("Connected to " + host + ".");
// JSch jsch=new JSch();
// Session session=jsch.getSession(username, host, port);
// session.setPassword(password);
// session.setUserInfo(defaultUserInfo);
// session.connect();
// Channel channel=session.openChannel("sftp");
// channel.connect();
// sftp=(ChannelSftp)channel;
} catch (Exception e) {
e.printStackTrace();
}
return sftp;
}
/**
* 上传文件
*
* @param directory
* 上传的目录
* @param uploadFile
* 要上传的文件
* @param sftp
*/
public void upload(String directory, String uploadFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
File file = new File(uploadFile);
sftp.put(new FileInputStream(file), file.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载文件
*
* @param directory
* 下载目录
* @param downloadFile
* 下载的文件
* @param saveFile
* 存在本地的路径
* @param sftp
*/
public void download(String directory, String downloadFile,
String saveFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
File file = new File(saveFile);
sftp.get(downloadFile, new FileOutputStream(file));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除文件
*
* @param directory
* 要删除文件所在目录
* @param deleteFile
* 要删除的文件
* @param sftp
*/
public void delete(String directory, String deleteFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
sftp.rm(deleteFile);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 列出目录下的文件
*
* @param directory
* 要列出的目录
* @param sftp
* @return
* @throws SftpException
*/
public Vector listFiles(String directory, ChannelSftp sftp)
throws SftpException {
return sftp.ls(directory);
}
public static void main(String[] args) {
MySFTP sf = new MySFTP();
String host = "127.0.0.1"; // 计算机名
int port = 1314; // 端口号
String username = "zhangjing"; // 用户名
String password = "1991"; // 密码
String directory = "/sftp"; // 读取文件的存放目录
String uploadFile = "D:\\TGData\\keywords.txt"; // 要上传的文件
// String downloadFile = "upload.txt"; //下载文件
// String saveFile = "D:\\tmp\\download.txt";//保存文件路径,和文件名
// String deleteFile = "delete.txt"; //要删除的文件名
ChannelSftp sftp = sf.connect(host, port, username, password);
sf.upload(directory, uploadFile, sftp); // 上传
// sf.download(directory, downloadFile, saveFile, sftp); //下载
// sf.delete(directory, deleteFile, sftp); //删除
try {
sftp.cd(directory);
try {
sftp.ls("/sftp"); // 首先查看下目录,如果不存在,系统会被错,捕获这个错,生成新的目录。
System.out.println("存在目录");
} catch (Exception e) {
sftp.mkdir("/sftp");
System.out.println("不存在目录,创建");
}
System.out.println("finished");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sftp != null) {
sftp.disconnect();
System.out.println("sftp is closed");
} else if (sftp == null) {
System.out.println("sftp is closed already");
}
}
}
}
本来这样是可以的.但是问题来了.在运行到ChannelSftp connect(String host, int port, String username, String password)方法中的sshSession.connect();方法时就报异常 java.net.SocketException: Software caused connection abort: recv failed.
网上查了下,原因可能是客户端和服务端建立tcp的短连接,每次客户端发送一次请求, 服务端响应后关闭与客户端的连接. 如果客户端在服务端关闭连接后,没有释放连接,继续试图发送请求和接收响应. 这个时候就会出错.
但是我和服务器端没有连接啊.不会出现没释放连接啊.
如果是代码的问题,上传也成功一次,但是仅仅一次.
不知道有没别的问题,
请各位大侠求教了.
--------------------编程问答-------------------- 最近也在弄这个,网上的例子几乎都不可靠,几乎所有人都只关了连接而没有关session
这一句 sshSession.connect();
sshSession打开了为啥不知道关呢,应该先关session,再关sftp连接。正确的关法:
if(sftp!=null){
if(sftp.getSession()!=null){
sftp.getSession().close;
}
sftp.disconnect();
}
你写得代码的正确性我就不做检查了,sftp默认端口号22,也可以改变 --------------------编程问答-------------------- 上面手动敲错了,抱歉应该是sftp.getSession().disconnect();知道意思就行了。可以写个定时任务不断的去连接,关闭,然后用netstat -an 看看连接有没有释放 --------------------编程问答-------------------- 我又犯错了,应该先关sftp再关session吧,心里这么想的,一写出来就错
补充:Java , 非技术区