You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dartssh2包连接SFTP列目录时遇SSH_Message_Request_Failure错误

Flutter使用dartssh2连接SFTP时遇到SSH_Message_Request_Failure错误

我在Flutter中使用dartssh2: ^2.10.0包连接SFTP服务器,SSH连接已成功建立,但调用目录列表操作时服务器返回SSH_Message_Request_Failure()错误,请求处理失败。

代码实现

SSHClient? _sshClient; 

Future<void> _connectSFTP() async {
  try {
    final socket = await SSHSocket.connect(
      'example.com',
      22,
    );
    _sshClient = SSHClient(
      socket,
      username: 'your-username',
      onPasswordRequest: () => 'your-password',
      printDebug: print, // 启用详细日志
      printTrace: print,
    );
    print('SSHClient connected to SFTP server.');
    await listRemoteDirectory();
  } catch (e) {
    if (e is SocketException) {
      print('Network error: $e'); 
    } else {
      print('Connection error: $e'); 
    }
  }
}

Future<void> listRemoteDirectory() async {
  try {
    final sftp = await _sshClient!.sftp();
    if (sftp == null) {
      return;
    }
    print('SFTP client created successfully.');

    const directoryPath = '/';

    // 为listdir操作添加超时
    final items = await sftp
        .listdir(directoryPath)
        .timeout(const Duration(seconds: 30));
    if (items.isEmpty) {
      print('The directory $directoryPath is empty.');
    } else {
      for (final item in items) {
        print('Item found: ${item.longname}');
      }
    }
  } on TimeoutException catch (e) {
    print('Timeout error occurred: $e');
  } on SftpStatusError catch (e) {
    print('SFTP status error: $e');
  } on SftpAbortError catch (e) {
    print('Operation aborted: $e');
  } on SftpExtensionUnsupportedError catch (e) {
    print('Unsupported extension: $e');
  } on SftpExtensionVersionMismatchError catch (e) {
    print('Extension version mismatch: $e');
  } catch (e) {
    print('An unexpected error occurred: $e');
  } finally {
    print('listRemoteDirectory method execution completed.');
  }
}

输出日志

I/flutter ( 2968): SSHClient connected to SFTP server
I/flutter ( 2968): <- _SSHNativeSocket(default.sftp.server:22): 
I/flutter ( 2968): <- _SSHNativeSocket(default.sftp.server:22): SSH_Message_Channel_Confirmation(recipientChannel: 0, senderChannel: 0)
I/flutter ( 2968): -> _SSHNativeSocket(default.sftp.server:22): SSH_Message_Channel_Request(recipientChannel: 0, requestType: subsystem, wantReply: true, subsystemName: sensor)
...
I/flutter ( 2968): <- _SSHNativeSocket(default.sftp.server:22): SSH_Message_Request_Failure()
I/flutter ( 2968): -> _SSHNativeSocket(default.sftp.server:22): SSH_Message_Global_Request(requestName: keepalive@openssh.com, wantReply: true)
...
I/flutter ( 9787): SFTP client created successfully.
**I/flutter ( 2968): <- _SSHNativeSocket(default.sftp.server:22): SSH_Message_Request_Failure()**
...

已尝试的排查操作

  • 通过命令行SFTP客户端验证路径正确,可正常列出目录
  • 确认SFTP用户拥有目标目录的访问权限
  • 测试多个目录路径,均无输出或报错
  • 添加超时处理和多类型错误捕获
  • 启用调试日志追踪请求流程

解决方案

1. 修正SFTP子系统名称

从日志可见,代码请求的子系统名称是sensor,而SFTP标准子系统名称应为sftp,这是核心问题。手动指定子系统名称创建SFTP客户端:

// 替换原有的final sftp = await _sshClient!.sftp();
final sftp = await _sshClient!.openSession().then((session) {
  return SftpClient(
    session,
    subsystemName: 'sftp', // 明确指定正确的子系统名称
  );
});

2. 验证服务器SFTP配置

检查服务器sshd_config文件,确保SFTP子系统配置正确,常见配置行:

Subsystem sftp /usr/lib/openssh/sftp-server

若使用internal-sftp,需确认配置生效且用户有权限访问。

3. 升级dartssh2版本

2.10.0版本可能存在子系统名称的bug,升级到最新版本尝试修复:

# pubspec.yaml中更新依赖
dependencies:
  dartssh2: ^latest_version

4. 确保SSH认证完成后再操作

在调用SFTP方法前,等待SSH客户端完成认证:

// 创建_sshClient后添加
await _sshClient!.authenticated;
print('SSHClient authenticated successfully.');
await listRemoteDirectory();

内容的提问来源于stack exchange,提问作者Clara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:46:02