简体   繁体   中英

SSH.NET Library - SshClient.Dispose(), public connection

I have 2 problems with using SSH.NET library.

I would like to create SSH connection and then disconnect. But if I start asynchronous read, disconnecting causes problems. My program simply freezes when I try to end a connection.

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
}

I also do not know how to create a connection that will be availbe from anywhere in the code. I would like to be able to define IP, UserName and Password (eg write them in some textBoxes), establish a connection and then interact with it by executing some commands and getting input. Passing the credentials, as I understand, requires some event hanlder (eg button1_Click), but then if I would like to interact with the created stream = ssh.CreateShellStream(...) by passing commands with eg button2_Click, I cannot do that because "The name "stream" does not exist in the current context".

Earlier I have been doing it by plik (from PuTTY) and Process functionality of C#:

private void ConnectButton_Click(object sender, EventArgs e)
{
    ...
    p = new Process();
    ...
    sw = p.StandardInput;
    ...
}

where sw is a streamwriter defined outside of the ConnectButton_Click event handler.

Thanks.

This is a deadlock. button1_Click is running on your UI thread, as is the Invoke inside of DataReceived .

SSH.NET does not internally use async -- all of it's "async" methods simply wrap a sync method in a thread pool and lock.

The flow will be this:

  1. BeginRead grabs hold of the lock and starts reading.
  2. Disconnect waits on the lock, in the UI thread, until `BeginRead is done with it.
  3. BeginRead finishes the read, and calls DataReceived which calls Invoke while still holding the lock.
  4. Invoke waits for the UI thread to process its message -- but it never will, because the UI thread is waiting on Disconnect .
  5. Now BeginRead and Disconnect are both waiting for each-other to finish -- a deadlock.

A quick way to test this would be to change the Invoke call to BeginInvoke , which will remove the deadlock.

As far as accessing these objects from anywhere in your Form , just make them members of the class.

I also stumbled accross this problem and the way I see it there is no way getting around this without modifying SSH.NET code. There is following block of code in SSH.NET, (Session.cs:584):

ExecuteThread(() =>
                    {
                        try
                        {
                            MessageListener();
                        }
                        finally
                        {
                            _messageListenerCompleted.Set();
                        }
                    });

This leads to following block of code(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();

inside disconnect it waits for _messageListenerCompleted.WaitOne() But this can never happen because _messageListenerCompleted.Set() is called in try{}finally{} block. So to solve this we should either call: _messageListenerCompleted.Set() before calling disconnect() during socket exception or handling Dissconnect somewhere outside

  SocketRead(int length, ref byte[] buffer)

function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM