在使用Ganymed API到SFTP时如何将本地地址绑定为源地址?

时间:2016-01-13 04:53:55

标签: java ssh sftp ssh2-sftp

我们正在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库中定义。

1 个答案:

答案 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新手,我花了我自己的美好时光才能做到这一点。没有人最有可能阅读或需要它,但发布此解决方案以防万一像我这样的人!