I have a test application which makes a single long-lasting connection to a servers (Well, a single connection to each server). This connection is 'maintained' via a function that is called in-between sets of command updates (Refreshes). Very single threaded approach...
private bool MaintainConnection()
{
bool connectionEstablished = false;
bool refreshConnection = false;
DateTime connectionRefreshTime = DateTime.Now.Add(new TimeSpan(0,0,-CONNECTIONREFRESHDELAY));
DateTime reconnectTime = DateTime.Now.Add(new TimeSpan(0,0,-RECONNECTDELAY));
//Disconnect for refresh
if (lastConnectAttempt < connectionRefreshTime)
{
if(this.client != null)
{
this.client.DisconnectSSH(); //Clean out connection
this.client = null;
refreshConnection = true;
}
}
//Connection or reconnection attempt
if (this.client == null)
{
if (lastConnectAttempt < reconnectTime)
Connect();
else
return false; //Bail out until it's time to reconnect
}
//Check the new connection
if(this.client != null && this.client.IsConnected())
{
//Do something that proves the connection works like sending data...
connectionEstablished = true;
}
//Check if we just lost the connection
if (this.isConnected && !connectionEstablished)
{
//Do something about it
}
//If the conneciton is dead, dispose of it
if(!connectionEstablished)
{
if(this.client != null)
{
this.client.DisconnectSSH();
this.client = null;
}
}
return connectionEstablished;
}
#endregion Private methods
}
I have a wrapper for my client with a few helper functions to assist in using SshNet: public virtual bool IsConnected()
{
return (this.client != null) && (this.client.IsConnected);
}
public bool ConnectSSH(bool pingCheck = false)
{
if (valid)
{
if (pingCheck)
{
PingReply reply = pinger.Send(hostname, 1000);
if (reply.Status != IPStatus.Success)
{
log.ERROR(
"Failed to connect SSH session, can not reach " +
this.hostname + "(Error = " +
reply.Status.ToString() + " )");
return false;
}
}
client = new SshClient(conn);
try
{
client.Connect();
return client.IsConnected;
}
catch (SshAuthenticationException e)
{
log.ERROR(e.Message +
" Check if the correct agent key is loaded for " +
this.username + "@" + this.hostname);
}
catch (System.Net.Sockets.SocketException e)
{
log.ERROR(e.Message);
}
catch (Exception e)
{
log.ERROR(e.Message);
}
}
return false;
}
public void DisconnectSSH()
{
try
{
if (this.client != null)
{
this.client.Disconnect();
this.client.Dispose();
this.client = null;
}
}
catch
{
//Ignore any errors
log.ERROR("SSH Client session did not disconnect cleanly.");
}
}
What you describe though doesn't sound like the problem I am having (Was having until I coded around it). I'm only creating a single channelsession for each server, but those were not garbage collected unless the entire client was disposed of.