我们正在Linux Server上部署Java项目。项目生成一个文件,然后将其发送到远程服务器。
之前使用Jsch实现了它。但是,由于它依赖于JCE并且无法升级java版本(从5开始),我们正在转向Ganymed。我正在使用Ganymed build 210(即测试java 5; http://www.ganymed.ethz.ch/ssh2)
这是我用来sftp文件的函数。
public boolean sftp_put() {
File privateKeyFile = new File(identityPath);
File rfile = new File(hostDir);
File lfile = new File(lpath);
boolean success = false;
try {
if (!lfile.exists() || lfile.isDirectory()) {
throw new IOException("Local file must be a regular file: "
+ lpath);
}
Connection ssh = new Connection(host, port);
ssh.connect();
ssh.authenticateWithPublicKey(user, privateKeyFile, password);
SFTPv3Client sftp = new SFTPv3Client(ssh);
try {
SFTPv3FileAttributes attr = sftp.lstat(hostDir);
if (attr.isDirectory()) {
rfile = new File(hostDir, lfile.getName());
}
} catch (SFTPException e) {
try {
SFTPv3FileAttributes attr = sftp.lstat(rfile.getParent());
if (!attr.isDirectory()) {
throw new IOException(
"Remote file's parent must be a directory: "
+ hostDir + "," + e);
}
} catch (SFTPException ex) {
throw new IOException(
"Remote file's parent directory must exist: "
+ hostDir + "," + ex);
}
}
SFTPv3FileHandle file = sftp.createFileTruncate(rfile
.getCanonicalPath());
long fileOffset = 0;
byte[] src = new byte[32768];
int i = 0;
FileInputStream input = new FileInputStream(lfile);
while ((i = input.read(src)) != -1) {
sftp.write(file, fileOffset, src, 0, i);
fileOffset += i;
}
input.close();
sftp.closeFile(file);
sftp.close();
success=true;
} catch (IOException e1) {
logger.warn("Exception while trying to sftp", e)
}
return success;
}
我无法连接到远程服务器可能是由于绑定问题而不确定如何继续?我正在考虑在SFTP之前绑定本地地址。
所以我写了一个套接字函数。
public Socket createSocket(String destinationHost, int destinationPort)
throws IOException, UnknownHostException {
logger.info("sftp configured bind address : " + bindAddress
+ ", bind port : " + bindPort);
Socket socket = new Socket();
socket.bind(new InetSocketAddress(bindAddress, bindPort));
socket.connect(new InetSocketAddress(destinationHost, destinationPort),
connectionTimeOut);
if (socket.isBound()) {
logger.info("sftp actual bind port : " + socket.getLocalPort());
} else {
logger.warn("sftp socket not bound to local port");
}
return socket;
}
然而,这也无效,我收到了Socket异常。
编辑:所以我正在以正确的方式创建套接字,但我没有在哪里使用相同的套接字来创建连接。这种方法没有在任何Ganymed库中定义。答案 0 :(得分:1)
由于ganymed中没有固有的方法,我编辑了源代码来编写方法。
以下是我所做的编辑。
到我正在使用的班级
SocketAddress sourceAddress = new InetSocketAddress(bindAddress,
bindPort);
Connection ssh = new Connection(host, port);
ssh.bindSourceAddress(sourceAddress);
ssh.connect();
然后我对Ganymed API的connection.class做了一些更改。相应地导入类和声明的变量
这是传递bindAddress的简单方法。
public void bindSourceAddress(SocketAddress sourceAddress) {
this.sourceAddress = sourceAddress;
}
使用initialize方法时将地址传递给Transport Manager类。
if (sourceAddress != null) {
tm.initialize(cryptoWishList, verifier, dhgexpara,
connectTimeout, getOrCreateSecureRND(), proxyData,
sourceAddress);
} else {
tm.initialize(cryptoWishList, verifier, dhgexpara,
connectTimeout, getOrCreateSecureRND(), proxyData);
}
修改了initialize方法的构造函数。它反过来调用一个建立连接函数,它被类似地修改以容纳SocketAddress。
private void establishConnection(ProxyData proxyData, int connectTimeout, SocketAddress sourceAddress) throws IOException
{
/* See the comment for createInetAddress() */
if (proxyData == null)
{
InetAddress addr = createInetAddress(hostname);
//test
if (sourceAddress != null) {
sock.bind(sourceAddress);
}
sock.connect(new InetSocketAddress(addr, port), connectTimeout);
sock.setSoTimeout(0);
return;
}
if (proxyData instanceof HTTPProxyData)
{
HTTPProxyData pd = (HTTPProxyData) proxyData;
/* At the moment, we only support HTTP proxies */
InetAddress addr = createInetAddress(pd.proxyHost);
//test
if (sourceAddress != null) {
sock.bind(sourceAddress);
}
sock.connect(new InetSocketAddress(addr, pd.proxyPort), connectTimeout);
sock.setSoTimeout(0);
最后绑定套接字。作为一个java新手,我花了我自己的美好时光才能做到这一点。没有人最有可能阅读或需要它,但发布此解决方案以防万一像我这样的人!