Reconnect sftp if connection is lost

0 votes
asked Jan 21, 2013 by fluxmunki (180 points)
edited Jan 23, 2013

I have a loop that attempts to retry sftp downloads. I'm testing it by killing my SFTP server during a download.

I'm having problems detecting when a reconnect sequence is required, and then performing the connect; is there a recommended way to do this?

I tried checking sftp.State but this is still "Ready" after the loss of connection, so I tried also checking sftp.Session.Connected when State is Ready (if you try and access sftp.Session otherwise you get an exception). This seems to let me detect when the connection has been lost. However if I then try and call sftp.Connect() I get an exception:

System.InvalidOperationException: Already connected to the server.
   at Rebex.Net.Sftp.2eOMSNZ(String , Int32 , SshParameters , ZD5WJ )
   at Rebex.Net.Sftp.iINPXZ(String , Int32 , SshParameters )
   at Rebex.Net.Sftp.Connect(String serverName, Int32 serverPort)

after I've had this exception once subsequent calls are ok.

I've now added call to sftp.Disconnect() when I detect the lost session, this seems to work, but I'm concerned that this feels a bit wrong and maybe it will break another scenario. It feels like there should be something in the Rebex SFTP library to handle this situation more gracefully, so I'm wondering if I'm missing a better way of doing this.

Here's the relevant bit of my code:

 if (client.State == SftpState.Ready && !client.Session.Connected)
    {
//if we've lost the session but the client still thinks its connected we'll have problems, so lets Disconnect it
      client.Disconnect();
    }

    if (client.State != SftpState.Ready)
    {
      client.Connect(configuration.Host, configuration.Port);          
      client.Login(configuration.Username, configuration.Password);
    }
Applies to: Rebex SFTP

1 Answer

0 votes
answered Jan 23, 2013 by Lukas Matyska (55,470 points)
edited Jan 23, 2013

Sftp object's State or GetConnectionState() or Session.Connected members return "Connected" if the connection is not currently known to have ended. If the connection was not closed yet by either the client or the server but it's already broken, mentioned members can still return "Connected" because the local machine is not yet aware that the connection has been lost.

Actually, the only reliable way to determine whether the connection is still active is to send a command over it - if the connection has already been lost, it won't be possible to transmit the command to the server.

However, sending a command to the SFTP server and waiting for failure or response may take many seconds to complete.

The code can look like this:

private bool IsConnectionAlive(Sftp client)
{
    try
    {
        client.GetInfo(".", false);
        return true;
    }
    catch (SftpException)
    {
        return false;
    }
}

Please note that this method works only after you are log in.

We will definitely add a method to get connection state in reliable way (and we will deprecate the mentioned members).

...