【问题标题】:Libssh2 stop reading large fileLibssh2 停止读取大文件
【发布时间】:2021-02-02 13:37:30
【问题描述】:

我需要通过 ssh 读取一些文件,但是当我循环读取文件时……它会停止。
在我的 Cargo.toml 我有这个依赖:

[dependencies]
ssh2 = "0.8"

这取决于 libssh2。
代码更复杂,但我设法用这个脏代码重现了问题:

  use std::fs::File;
  use std::io::Read;
  use std::io::Write;
  #[allow(unused_imports)]
  use std::io::Error;
  use std::net::TcpStream;
  use ssh2::Session;
  use std::path::Path;
  use std::io::prelude::*;

  fn main() {
      println!("Parto!");

      let tcp = TcpStream::connect("myhost:22").unwrap();
      let mut sess = Session::new().unwrap();
      sess.set_tcp_stream(tcp);
      sess.handshake().unwrap();
      sess.userauth_password("user", "password").unwrap();
      assert!(sess.authenticated());

      let (mut remote_file, stat) = sess.scp_recv(Path::new("/home/pi/dbeaver.exe")).unwrap();
      println!("remote file size: {}", stat.size());
      let mut buf: Vec<u8> = vec![0;1000];

      loop {
          let read_bytes = remote_file.read(&mut buf).unwrap();
          println!("Read bytes: {}.", read_bytes);
          if read_bytes < 1000 {
              break;
          }
      } //ending loop
  }

我在 Windows 10 和 Linux Debian 上都进行了测试。当读取的文件超过几 KB 时,问题总是存在:

let read_bytes = remote_file.read(&mut buf).unwrap();

读取小于缓冲区大小(但文件未结束)。
用二进制或 asci 文件测试。

没有错误,它只是停止阅读。奇怪的是:它有时停在 8 MB,有时停在 16 KB。涉及相同的文件和主机...

我需要在哪里挖掘或需要检查什么?

【问题讨论】:

  • 您是否使用不同的主机/本地主机(如果可能)对其进行了测试以排除远程主机问题?
  • @GrayCat 我用 2 台不同的远程主机进行了测试,一台 Raspberry 和一台 Debian。我会去本地再做一次测试阅读。

标签: rust libssh2


【解决方案1】:

引用io::Read trait(ssh2 实现)的文档:

如果返回值 n 小于缓冲区大小,则不是错误,即使读取器尚未位于流的末尾。例如,这可能是因为现在实际可用的字节数较少(例如,接近文件结尾)或因为 read() 被信号中断。

由于您正在远程读取,这可能只是意味着剩余字节仍在网络中传输,并且尚未在目标计算机上可用。

如果您确定有足够的传入数据来填充缓冲区,则可以使用read_exact,但请注意,如果可用数据短于缓冲区,则会返回错误。

编辑:或者更好的是,使用read_to_end,它不需要事先知道大小(我不知道为什么我昨天写原始答案时看不到它)。

【讨论】:

  • 我可以读取文件大小,所以我想我可以使用 read_exact 管理读取。我要试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多