Hello,
with a shell in nonblocking mode, OnAsyncReceive doesn't raise.
part of my code:
class TThreadSshClient : public TThread
{
private:
struct DeviceInfo &Infos;
TScSSHClient *ScSSHClient1;
TScFileStorage *ScFileStorage1;
TScSSHShell *ScSSHShell1;
...
void __fastcall ScSSHClientServerKeyValidate(TObject *Sender, TScKey *NewServerKey, bool &Accept);
void __fastcall ScSSHShellOnAsyncReceive(TObject *Sender);
};
...
ScSSHClient1 = new TScSSHClient(Owner);
ScFileStorage1 = new TScFileStorage(Owner);
ScSSHShell1 = new TScSSHShell(Owner);
ScSSHClient1->KeyStorage = ScFileStorage1;
ScSSHClient1->OnServerKeyValidate = ScSSHClientServerKeyValidate ;
ScSSHShell1->Client = ScSSHClient1;
ScSSHShell1->OnAsyncReceive = ScSSHShellOnAsyncReceive;
ScSSHShell1->NonBlocking = true;
...
//---------------------------------------------------------------------------
void __fastcall TThreadSshClient::ScSSHShellOnAsyncReceive(TObject *Sender)
{
char buffer[10005];
int ReadBytes = ScSSHShell1->ReadBuffer(buffer, sizeof(buffer));
if(ReadBytes == 0)
throw EAbort("Failed. (ReadBytes == 0) Unexpected disconnection");
Text += AnsiString(buffer, ReadBytes);
}
------------------------------------------------------------------------
I made a tempory work around using a loop with a timeout, it's working fine but it's not very satisfying:
...
while (!Terminated && ScSSHShell1->Connected && i_SSHReceivedTimeOutReadBuffer(buffer, sizeof(buffer));
if(ReadBytes != 0)
Text += AnsiString(buffer, ReadBytes);
}
----------------------------------------------------------------
I have also a question about OnAsyncReceive:
when exaclty should it be raise please?
each time there is an action (write read..)or only on read? for each characters or only one time per message?
have you exemple using OnAsyncReceive (there is no demo in secure bridge for C++Builder5)
Thanks for your help.
regards.
TScSSHShell: OnAsyncReceive event never raise
This problem occurred because you create and start TScSSHClient and TScSSHShell in separate thread. TScSSHShell in NonBlocking mode uses own thread and therefore you don't need to use another thread. You can use this functionality in the main thread without performance penalty.
Or, at least, for solving the problem, you should set although one SSH connection in the main thread.
Or, at least, for solving the problem, you should set although one SSH connection in the main thread.
Hello,
I've the same problem.
TScSshClient and TScSshShell instancse are created in the same thread.
But is not the main thread.
onAsync event will not be raised - for whatever reason.
The application is a command line application.
The instances of TJob will be called in a separate Thread.
That is because the application is trying to access some sshTarget in "parallel".
Maybe there is a stupid failure in that code- but I don't see it.
Best regards
Klaus
I've the same problem.
TScSshClient and TScSshShell instancse are created in the same thread.
But is not the main thread.
Code: Select all
procedure TJobs._OnAsyncReceive(sender: TObject);
var
s: ansiString;
begin
(sender as TscSshShell).ReadBuffer(s,(sender as TscSshShell).InCount);
logger.add('ar '+s,0);
end;
Code: Select all
function TJobs._doJob(sshTarget: AnsiString):Boolean;
var
sshClient : TScSshClient;
sshKeyStorage : TScFileStorage;
sshChannel : TscSSHChannel;
sshShell : TScSshShell;
begin
sshKeyStorage := TScFileStorage.Create(nil);
sshClient := TScSshClient.Create(nil);
sshShell := TscSshShell.Create(nil);
try
try
sshClient.KeyStorage := sshKeyStorage;
sshClient.Authentication := ScSSHUtil.atPassword;
sshClient.User := configData.sysUsername;
sshClient.Password := configData.sysPassword;
sshClient.HostName := sshTarget;
sshClient.Port := configData.SSHPort;
sshClient.OnServerKeyValidate := _onServerKeyValidate;
sshShell := TscSshShell.Create(nil);
try
sshShell.NonBlocking := true;
sshShell.OnAsyncReceive := _onAsyncReceive;
sshShell.Client := sshClient;
sshShell.NonBlocking := true;
sshShell.Connect;
if sshShell.Connected then
begin
s:='ls -l';
sshShell.WriteString(s);
sleep(250);
// s := sshShell.ReadString;
// logger.add(s,0);
end;
finally
if sshShell.Connected then
sshShell.Disconnect;
if sshClient.Connected then
sshClient.Disconnect;
sshShell.Free;
end;
except
on E:Exception do
begin
logger.add(format('error - %s',[E.Message]));
end;
end;
finally
sshClient.Free;
end;
...
The application is a command line application.
The instances of TJob will be called in a separate Thread.
That is because the application is trying to access some sshTarget in "parallel".
Maybe there is a stupid failure in that code- but I don't see it.
Best regards
Klaus