编辑
2025-02-19
C# 应用
00
请注意,本文编写于 76 天前,最后修改于 76 天前,其中某些信息可能已经过时。

目录

安装
基本用法
连接到 SSH 服务器
执行远程命令
高级用法
使用密钥认证
SFTP 文件传输
上传
下载
端口转发
执行多个命令
使用 SCP 传输文件
3.6 异步操作
处理大文件传输
错误处理和最佳实践
使用 try-catch 块
使用 using 语句
检查连接状态
设置超时
结论

SSH.NET 是一个功能丰富的 .NET SSH 客户端库,它提供了一个简单而强大的 API 来执行各种 SSH 操作。本文将详细介绍 SSH.NET 的使用方法,并提供多个实用的例子。

安装

首先,通过 NuGet 包管理器安装 SSH.NET

C#
Install-Package SSH.NET

image.png

基本用法

连接到 SSH 服务器

C#
using Renci.SshNet; using System; class Program { static void Main(string[] args) { string host = "127.0.0.1"; string username = "rick"; string password = "123456"; using (var client = new SshClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to the SSH server!"); // 执行其他操作... client.Disconnect(); Console.WriteLine("Disconnected from the SSH server."); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } } }

image.png

执行远程命令

C#
static void Main(string[] args) { string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SshClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to the SSH server!"); using (var cmd = client.CreateCommand("ls -l")) { var result = cmd.Execute(); Console.WriteLine("Command output:"); Console.WriteLine(result); } client.Disconnect(); Console.WriteLine("Disconnected from the SSH server."); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } }

image.png

高级用法

使用密钥认证

C#
using Renci.SshNet; using System.IO; class Program { static void Main(string[] args) { string host = "127.0.0.1; string username = "rick"; string privateKeyFile = @"D:\private_key.pem"; using (var stream = new FileStream(privateKeyFile, FileMode.Open, FileAccess.Read)) { var privateKeyFile = new PrivateKeyFile(stream); var privateKeyFiles = new[] { privateKeyFile }; using (var client = new SshClient(host, username, privateKeyFiles)) { client.Connect(); Console.WriteLine("Connected using private key authentication!"); // 执行其他操作... client.Disconnect(); } } } }

SFTP 文件传输

上传

C#
static void Main(string[] args) { // SFTP服务器的连接参数 string host = "127.0.0.1"; // 服务器地址(本地主机) string username = "trueideal"; // SFTP用户名 string password = "123456"; // SFTP密码 // 创建SFTP客户端实例并确保资源正确释放 using (var client = new SftpClient(host, username, password)) { try { // 尝试连接到SFTP服务器 client.Connect(); Console.WriteLine("已成功连接到SFTP服务器!"); // 列出当前用户主目录下的文件 // 使用 "." 表示当前目录,这通常比使用 "/" 根目录有更高的成功率 var files = client.ListDirectory("."); foreach (var file in files) { // 打印每个文件的名称和大小 Console.WriteLine($"{file.Name} - {file.Length} 字节"); } // 上传文件到SFTP服务器 // 打开本地文件并上传到用户的主目录 using (var fileStream = new FileStream(@"D:\Archive.csv", FileMode.Open)) { // './Archive.csv' 表示上传到当前用户的主目录 client.UploadFile(fileStream, "./Archive.csv"); } // 完成操作后断开连接 client.Disconnect(); } catch (Exception ex) { // 错误处理 Console.WriteLine($"发生错误: {ex.Message}"); // 输出详细的错误信息,包括堆栈跟踪等 Console.WriteLine($"错误详情: {ex}"); } } }

image.png

下载

C#
static void Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SftpClient(host, username, password)) { try { // 连接到SFTP服务器 client.Connect(); Console.WriteLine("已成功连接到SFTP服务器!"); // 列出服务器上可供下载的文件 Console.WriteLine("\n当前目录下的文件列表:"); var files = client.ListDirectory("."); foreach (var file in files) { Console.WriteLine($"{file.Name} - {file.Length} 字节"); } // 下载文件示例1:下载到指定路径 string remoteFile = "./Archive.csv"; // SFTP服务器上的文件路径 string localPath = @"D:\Downloads\"; // 本地保存目录 string localFile = Path.Combine(localPath, "Downloaded_Archive.csv"); // 本地完整文件路径 // 确保本地目录存在 Directory.CreateDirectory(localPath); // DownloadFile方法 using (var fileStream = File.Create(localFile)) { Console.WriteLine($"\n开始下载文件: {remoteFile}"); client.DownloadFile(remoteFile, fileStream); Console.WriteLine($"文件已下载到: {localFile}"); } // 断开连接 client.Disconnect(); Console.WriteLine("已断开与SFTP服务器的连接。"); } catch (Exception ex) { // 错误处理 Console.WriteLine($"\n发生错误: {ex.Message}"); if (ex is FileNotFoundException) { Console.WriteLine("远程文件不存在!"); } else if (ex is DirectoryNotFoundException) { Console.WriteLine("本地目录不存在!"); } else if (ex is IOException) { Console.WriteLine("文件读写错误!"); } Console.WriteLine($"详细错误信息: {ex}"); } } Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); }

端口转发

C#
static void Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SshClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to SSH server!"); // 本地端口转发 var forwardedPort = new ForwardedPortLocal("127.0.0.1", 8080, "remote.example.com", 80); client.AddForwardedPort(forwardedPort); forwardedPort.Start(); Console.WriteLine("Port forwarding started. Press any key to stop..."); Console.ReadKey(); forwardedPort.Stop(); client.Disconnect(); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } }
  • 将本地端口的连接转发到远程服务器
  • 访问localhost:8080实际上访问的是remote.example.com:80

执行多个命令

C#
static void Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SshClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to SSH server!"); // 执行多个命令 using (var shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024)) { shellStream.WriteLine("cd /tmp"); shellStream.WriteLine("mkdir test_folder"); shellStream.WriteLine("ls -l"); shellStream.WriteLine("exit"); string line; while ((line = shellStream.ReadLine()) != null) { Console.WriteLine(line); } } client.Disconnect(); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } }

image.png

使用 SCP 传输文件

C#
static void Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new ScpClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to SCP server!"); // 上传文件 client.Upload(new FileInfo(@"C:\local\file.txt"), "/remote/path/file.txt"); Console.WriteLine("File uploaded successfully!"); // 下载文件 client.Download("/remote/path/file.txt", new FileInfo(@"C:\local\downloaded_file.txt")); Console.WriteLine("File downloaded successfully!"); client.Disconnect(); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } }

3.6 异步操作

C#
static async Task Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SshClient(host, username, password)) { try { var timeout = TimeSpan.FromSeconds(30); using (var cts = new CancellationTokenSource(timeout)) { await client.ConnectAsync(cts.Token); Console.WriteLine("Connected to SSH server!"); var command = client.CreateCommand("ls -l"); // 异步执行命令 await command.ExecuteAsync(cts.Token); // 命令执行完成后,可以通过Result属性获取输出 string result = command.Result; Console.WriteLine($"Command output: {result}"); // 如果需要错误输出 if (!string.IsNullOrEmpty(command.Error)) { Console.WriteLine($"Error output: {command.Error}"); } // 如果需要获取退出状态码 int? exitStatus = command.ExitStatus; Console.WriteLine($"Exit status: {exitStatus}"); } client.Disconnect(); } catch (OperationCanceledException) { Console.WriteLine("Operation timed out"); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } finally { if (client.IsConnected) { client.Disconnect(); } } } }

image.png

处理大文件传输

C#
static async Task Main(string[] args) { // SFTP服务器连接参数 string host = "127.0.0.1"; string username = "trueideal"; string password = "123456"; using (var client = new SftpClient(host, username, password)) { try { client.Connect(); Console.WriteLine("Connected to SFTP server!"); // 上传大文件 using (var fileStream = new FileStream(@"C:\local\large_file.zip", FileMode.Open)) { client.BufferSize = 4 * 1024; // 设置缓冲区大小为4K client.UploadFile(fileStream, "/remote/path/large_file.zip", true, (uploaded) => { Console.WriteLine($"Uploaded: {uploaded} bytes"); }); } Console.WriteLine("Large file uploaded successfully!"); client.Disconnect(); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } }

错误处理和最佳实践

使用 try-catch 块

始终使用 try-catch 块来处理可能出现的异常:

C#
try { using (var client = new SshClient(host, username, password)) { client.Connect(); // 执行操作... client.Disconnect(); } } catch (Renci.SshNet.Common.SshAuthenticationException ex) { Console.WriteLine($"Authentication failed: {ex.Message}"); } catch (Renci.SshNet.Common.SshConnectionException ex) { Console.WriteLine($"Connection failed: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"An unexpected error occurred: {ex.Message}"); }

使用 using 语句

总是使用 using 语句来确保资源被正确释放:

C#
using (var client = new SshClient(host, username, password)) { // 使用客户端... }

检查连接状态

在执行操作之前,始终检查连接状态:

C#
if (!client.IsConnected) { client.Connect(); }

设置超时

为长时间运行的操作设置超时:

C#
client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(30);

结论

SSH.NET 是一个功能强大且易于使用的 SSH 客户端库。它提供了广泛的功能,从基本的 SSH 连接和命令执行到高级的文件传输和端口转发。通过本文提供的示例,你应该能够处理大多数 SSH 相关的任务。

使用 SSH.NET 可以极大地简化在 C# 应用程序中实现 SSH 功能的过程。无论是系统管理、自动化部署还是远程数据处理,SSH.NET 都是一个excellent选择。

在使用 SSH.NET 时,请记住正确处理异常,并考虑网络连接的不稳定性。对于需要处理大文件或执行长时间运行的操作的情况,可能需要考虑使用异步方法和进度回调。

希望这篇文章对你有所帮助,祝你在 C# 开发中使用 SSH.NET 愉快!

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!