使用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
相关产品推荐
相关产品推荐

