SSH.NET Library - SshClient.Dispose(),公共连接
本文关键字:连接 Dispose NET Library SshClient SSH | 更新日期: 2023-09-27 18:17:25
我在使用 SSH.NET 库时遇到 2 个问题。
我想创建SSH连接,然后断开连接。但是,如果我开始异步读取,断开连接会导致问题。当我尝试结束连接时,我的程序只是冻结。
public void button1_Click(object sender, EventArgs e)
{
var ssh = new SshClient(IP, UserName, Password);
ssh.Connect();
var stream = ssh.CreateShellStream("anything", 80, 24, 800, 600, 4096);
byte[] buffer = new byte[1000];
stream.BeginRead(buffer, 0, buffer.Length, null, null);
stream.DataReceived += new EventHandler<Renci.SshNet.Common.ShellDataEventArgs>(
(s, ex) =>
{
Invoke((MethodInvoker)delegate
{
textBox1.AppendText(stream.Read());
});
}
);
stream.WriteLine("ls");
stream.Dispose();
ssh.Disconnect(); //problem here
}
我也不知道如何创建一个可以从代码中的任何位置使用的连接。我希望能够定义IP,用户名和密码(例如将它们写入某些文本框中(,建立连接,然后通过执行一些命令和获取输入来与之交互。据我了解,传递凭据需要一些事件 hanlder(例如 button1_Click(,但是如果我想通过传递带有 button2_Click 的命令来与创建的stream = ssh.CreateShellStream(...)
进行交互,我不能这样做,因为"名称"流"在当前上下文中不存在"。
早些时候我一直在通过 plik(来自 PuTTY(和 C# 的流程功能来做到这一点:
private void ConnectButton_Click(object sender, EventArgs e)
{
...
p = new Process();
...
sw = p.StandardInput;
...
}
其中 sw 是在 ConnectButton_Click 事件处理程序之外定义的流编写器。
谢谢。
死锁。 button1_Click
在您的 UI 线程上运行,DataReceived
内部的Invoke
也是如此。
SSH.NET 内部不使用异步 - 它所有的"异步"方法都只是将同步方法包装在线程池中并锁定。
流程将是这样的:
-
BeginRead
抓住锁,开始阅读。 -
Disconnect
在 UI 线程中等待锁,直到"开始阅读"完成。 -
BeginRead
完成读取,并调用DataReceived
,Invoke
同时仍按住锁。 -
Invoke
等待 UI 线程处理其消息 - 但它永远不会,因为 UI 线程正在等待Disconnect
。 - 现在
BeginRead
和Disconnect
都在等待对方的结束——一个僵局。
测试这一点的一种快速方法是将Invoke
调用更改为 BeginInvoke
,这将消除死锁。
至于从Form
中的任何位置访问这些对象,只需使它们成为类的成员即可。
我也偶然发现了这个问题,在我看来,如果不修改 SSH.NET 代码就无法解决这个问题。SSH.NET 中有以下代码块(会话.cs:584(:
ExecuteThread(() =>
{
try
{
MessageListener();
}
finally
{
_messageListenerCompleted.Set();
}
});
这会导致以下代码块(Session.NET.cs:220(:
partial void SocketRead(int length, ref byte[] buffer)
..
catch (SocketException exp) {
if (exp.SocketErrorCode == SocketError.ConnectionAborted)
{
buffer = new byte[length];
Disconnect();
内部断开连接它等待_messageListenerCompleted.WaitOne((但这永远不会发生,因为 try{}finally {} 块中调用了 _messageListenerCompleted.Set((。因此,要解决此问题,我们应该调用:_messageListenerCompleted.Set(( 在套接字异常期间调用 disconnect(( 或处理外部某处断开连接之前
SocketRead(int length, ref byte[] buffer)
功能。