【问题标题】:Slow transfer using JSch from SFTP file transfer on Android在 Android 上使用 JSch 从 SFTP 文件传输缓慢传输
【发布时间】:2015-07-18 18:08:21
【问题描述】:

我正在使用 JSch 在 Android 中执行 SFTP 下载。这是在具有 802.11n 的 LAN 和有线千兆位连接上的 SFTP 服务器上。我在具有相同代码的笔记本电脑(也是 802.11n)上获得大约 8 mbytes/sec,但在 Android 上我只能获得 40kbytes/sec。是否有一些标志或我需要打开的东西才能让它更快地传输?我已经在 Nexus 5 和 Nexus 6 上尝试过,两者都是 5.1。我尝试了几个应用程序,一个以 230kbytes/sec 的速度下载了文件,另一个以 40kbytes/sec 的速度下载了文件,所以我猜其中一个与我有同样的问题。

这是我的代码:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    JSch jsch = new JSch();

                    jsch.setConfig("StrictHostKeyChecking", "no");
                    Session session = jsch.getSession("ftptest", "192.168.1.205");

                    session.setPort(22);
                    session.setPassword("password");
                    session.connect();
                    ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
                    channel.connect();
                    SftpProgressMonitor monitor = new SftpProgressMonitor() {
                        long finalCount = 0;
                        long start = -1;

                        @Override
                        public void init(int op, String src, String dest, long max) {
                            start = System.currentTimeMillis();
                        }

                        @Override
                        public boolean count(long count) {
                            finalCount += count;
                          /*  long took = (System.currentTimeMillis() - start) / 1000;
                            if (took > 0) {
                                Log.w("SFTP", "Transferred so far " + finalCount + " at speed bytes/sec " + (finalCount / took));
                            }*/
                            return true;
                        }

                        @Override
                        public void end() {
                            long took = (System.currentTimeMillis() - start) / 1000;
                            Log.w("SFTP", "Transferred " + finalCount + " in " + took + " speed bytes/sec " + (finalCount  / took ));
                        }
                    };
                    InputStream stream = channel.get("file", monitor);
                    int read = -1;
                    byte[] bs = new byte[8192];
                    while((read = stream.read(bs)) >= 0){
                        //do nothing
                    }
                } catch (JSchException e) {
                    e.printStackTrace();
                } catch (SftpException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();
    }


}

编辑:如果我告诉它在不给我 InputStream 的情况下将流写入文件,它似乎要快得多(大约 160kbytes/sec)。两种get 方法之间的代码看起来非常不同,但即使我走那条路,160kbytes/sec 仍然比我希望的要慢得多。

【问题讨论】:

  • 您可能会用尽硬件。看看你是否可以收集 CPU/IO 数据。
  • 也许是这样,但我在我的 GS3 测试设备上只看到大约 40% 到 60% 的使用率,这是表现最差的。 Nexus 4 和 Nexus 6 的速度非常相似。
  • 我刚刚确认这不是硬件限制,另一个名为 sshj 的库可以以超过 1mbyte/sec 的速度下载文件。
  • 玩转新字节[8192]:将大小从 1k 到 32k (1,2,4,8,16,32) 不同,看看是否有区别。除了硬件之外,您还可能在网络级别遇到延迟、包碎片等问题
  • 我尝试了许多不同的尺寸并将其包装在缓冲区上,但似乎都没有帮助。使用他们下载到输出流的方法,我确实获得了更快的速度,但与 sshj 相比,它仍然非常慢。

标签: android ssh sftp jsch android-networking


【解决方案1】:

您正在使用哪个版本的 Android 进行测试?你可以 adb shell 看看这些设置是什么(当你在 wifi 上时)?

cat /proc/sys/net/ipv4/tcp_rmem
cat /proc/sys/net/ipv4/tcp_wmem

然后如果它们很低(例如“4092 8760 11680”),则尝试将它们设置为更大的值:

sudo echo "524288,1048576,2097152" > /proc/sys/net/ipv4/tcp_rmem
sudo echo "262144,524288,1048576" > /proc/sys/net/ipv4/tcp_wmem

然后再试一次。

这可能是由于在某些情况下 wifi 缓冲区设置得太小 (https://code.google.com/p/android/issues/detail?id=64706) 造成的。

【讨论】:

  • 还有一个应用程序可以为您设置这些值(它仍然需要 root 访问权限):play.google.com/store/apps/…
  • 嗯,我看看能不能找到一个设备来测试它,我的测试设备都没有root。
  • 至少尝试对文件进行分类,您可以查看它们是否设置了小的缓冲区(我相信您可以在没有 root 的情况下这样做)。
  • 在 Nexus 4 上 rmem 有 524288 1048576 2097152 和 wmem 262144 524288 1048576
  • 另外我不知道你是否看到了我与其他人交换的其他消息,但基本上手机中的其他应用程序也可以使用 SFTP 获得良好的速度,并且一个名为 sshj 的库获得大约 1 mbyte/秒在同一部手机上。我现在正在切换到 sshj。
【解决方案2】:

您是否尝试将流包装在缓冲流中?

 BufferedInputStream bis = new BufferedInputStream(channel.get("file", monitor));

8192 字节似乎是一个小缓冲区......

还要确保关闭连接/流,也许您有很多不知道的传出连接会占用硬件?

【讨论】:

  • 是的,我试过用几种尺寸包装它。它发生在多部手机上,我已经杀死了之前可以在手机上测试的所有应用程序。就像我在另一条评论中所说的那样,sshj 快得多,所以我现在要这样做。
猜你喜欢
  • 2013-02-13
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
相关资源
最近更新 更多