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

How to bind a local address as the source address while using Ganymed API to SFTP?

我们正在 Linux 服务器上部署 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 之前绑定一个本地地址。

所以我写了一个socket函数

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;
}

但是这也不起作用,我得到了套接字异常。

编辑:所以我以正确的方式创建了套接字,但不知道我在哪里使用相同的套接字来创建连接。这种方法在任何 Ganymed 库中都没有定义。

由于ganymed中没有固有方法,所以我编辑了源代码写了一个方法。

以下是我所做的编辑。

到我正在使用

的 class
SocketAddress sourceAddress = new InetSocketAddress(bindAddress,
                bindPort);
        Connection ssh = new Connection(host, port);
        ssh.bindSourceAddress(sourceAddress);
        ssh.connect();

然后我对 Ganymed API 的 connection.class 做了一些修改。导入 class 并相应地声明变量

这是传递绑定地址的简单方法。

public void bindSourceAddress(SocketAddress sourceAddress) {
            this.sourceAddress = sourceAddress;
        }

使用初始化方法时将地址传递给传输管理器class。

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);

终于绑定了socket。作为一个 java 新手,我花了我自己的甜蜜时间来做对。很可能没有人会阅读或需要它,但发布此解决方案以防万一像我这样的人!