问题
I am trying to write an SSH script for some routers/switches to read out information using SSH.Net. I want to build it asynchronous because they are pretty slow with high latency.
I can connect and send a command, but if I try to read it out, I just get some blank lines. If I run the WriteLine()
method like 7 times in a row, I see like 2 of the expected outputs. I hope you can help me.
Here is my code:
private static string _srv = "255.255.255.255";
private static string _usr = "looping";
private static string _pwd = "louie";
static void Main(string[] args)
{
GetDslamData();
Console.ReadKey();
}
private static async void GetDslamData()
{
using (SshClient _ssh = new SshClient(_srv, _usr, _pwd))
{
try
{
_ssh.Connect();
if (_ssh.IsConnected)
{
ShellStream stream = _ssh.CreateShellStream("mainstream", 0, 0, 0, 0, 2048);
if (stream.CanWrite)
{
stream.WriteLine("help");
}
if (stream.CanRead)
{
byte[] buffer = new byte[2048];
int i = 0;
if ((i = await stream.ReadAsync(buffer, 0, buffer.Length)) != 1)
{
Console.WriteLine(_ssh.ConnectionInfo.Encoding.GetString(buffer, 0, i));
}
}
}
_ssh.Disconnect();
_ssh.Dispose();
}
catch (Exception ex)
{
Console.WriteLine("Verbindungsfehler! Es konnte keine SSH-Session gestartet werden.");
}
}
}
回答1:
First, you're disposing _ssh
twice; once explicitly, then again implicitly when you leave the using()
scope - you should drop the first one.
Second, because you're not awaiting GetDslamData()
you're dropping straight through to Console.ReadKey()
while GetDslamData()
keeps running. While much of Console
is thread safe, there are at least some reports of performing WriteLine()
while in a ReadKey()
causing deadlocks or other unwelcome behaviour; e.g.:
Strange behaviour of Console.ReadKey() with multithreading
http://putridparrot.com/blog/console-readkey-and-console-writeline-deadlock/
Calling Console.WriteLine from multiple threads
So instead, change your GetDslamData()
signature to this:
private static async Task GetDslamData()
and Main()
to this:
static void Main(string[] args)
{
GetDslamData().GetAwaiter().GetResult();
Console.ReadKey();
}
or if you are using C# 7.1+, to this:
static async Task Main(string[] args)
{
await GetDslamData();
Console.ReadKey();
}
That way ReadKey()
won't be executed until GetDslamData()
is complete. If you only had the ReadKey()
there because you noticed your app was otherwise exiting immediately, just drop it after changing the code as above.
来源:https://stackoverflow.com/questions/48808074/c-sharp-ssh-net-asynchronous-command-read-and-write