Board index » delphi » IdTelnet (Indy 10): Multi - Telnet sessions.
jimmydorsey
![]() Delphi Developer |
IdTelnet (Indy 10): Multi - Telnet sessions.2006-07-28 01:30:17 AM delphi249 I am trying to create an application that connects(telnet) to multiple(8 to 20+) unix boxes and executes a list of several commands. The list of servers is loaded via an INI file. A TMemo and TIdTelnet are placed on a frame and are created dynamically on a TTabSheet(in a TPageControl) base on the number of entries in the INI file. So far it seems to work for about 3 or less connections. On the fourth and more, I start getting hangs. The application becomes unresponsive. Occasionally it returns - only to become unresponsive again. I am alittle unsure as to which way to go now. I suspect my design is at fault, but it could simply be my implementation. Am I being unrealistic? I am thinking that this should be accomplishable for the magnitude(20-25) that I am looking at. I haven't created threads for each dynamic tab - I assume some threading is done in the component, but not sure exactly how that playes into it. Do I need to create my own threads for each? I'll post code so as to skip that request ;-) Thanks in advance for any help. any streamlining on the component searching would be nice also. It is 280 lines or so including Francois Piette's demo code for the DataAvailable. I use long lines to(well past 80 sometimes) - sorry. unit fOctopus; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Menus, StdCtrls, ComCtrls, ToolWin, IniFiles, Dialogs, ImgList, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTelnet, fTelnet; //****************************************************************************** type TSite = record site : string; visn : string; moniker : string; id : string; server : string; port : integer; FContinue: boolean; end; //****************************************************************************** TfrmOctopus = class(TForm) MainMenu1: TMainMenu; statusBar: TStatusBar; File1: TMenuItem; Connection1: TMenuItem; Help1: TMenuItem; ToolBar1: TToolBar; tbtnConnect: TToolButton; tbtnLogin: TToolButton; tbtnUpCarat: TToolButton; ToolButton4: TToolButton; ToolButton5: TToolButton; ToolButton6: TToolButton; ToolButton7: TToolButton; ToolButton8: TToolButton; ToolButton9: TToolButton; ToolButton10: TToolButton; tbtnDisconnect: TToolButton; memoSites: TMemo; ToolButton12: TToolButton; imagesEnabled: TImageList; imagesDisabled: TImageList; tabPage: TPageControl; editAccess: TEdit; ToolButton1: TToolButton; editVerify: TEdit; lblVerify: TLabel; ToolButton13: TToolButton; lblAccess: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Connect(Sender: TObject); procedure Disconnect(Sender: TObject); //------------------------------------------------ procedure telnetClientDataAvailable(Sender: TIdTelnet; const Buffer: String); procedure telnetClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String); //------------------------------------------------ private { Private declarations } FOctopusINI: TIniFile; FSites: array of TSite; FslSitelist: TStringlist; public { Public declarations } procedure ImportINI; procedure SetSites(i: integer); procedure SendCommand(S: string; telnetToSendTo: TIdTelnet); end; //****************************************************************************** var frmOctopus: TfrmOctopus; implementation {$R *.dfm} //****************************************************************************** procedure TfrmOctopus.ImportINI; var iniSectionName: string; i: integer; begin memoSites.Clear; FOctopusINI := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Octopus.ini'); with FOctopusINI do begin FslSitelist := TStringlist.Create; FslSitelist.Clear; FOctopusINI.ReadSection('Sites', FslSitelist); if (FslSitelist.Count>0) then begin SetLength(FSites, FslSitelist.Count); for i := 0 to (FslSitelist.Count - 1) do begin iniSectionName := FOctopusINI.ReadString('Sites', 'site' + IntToStr(Ord(i)), ''); with FSites[i] do begin site := FOctopusINI.ReadString(iniSectionName, 'site', ''); visn := FOctopusINI.ReadString(iniSectionName, 'visn', ''); moniker := FOctopusINI.ReadString(iniSectionName, 'moniker', ''); id := FOctopusINI.ReadString(iniSectionName, 'id', ''); server := FOctopusINI.ReadString(iniSectionName, 'server', ''); port := FOctopusINI.ReadInteger(iniSectionName, 'port', 0); FContinue := TRUE; end; memoSites.Lines.Add(FSites[i].site); end; end; end; end; //****************************************************************************** procedure TfrmOctopus.SetSites(i: integer); var tabClients: TTabSheet; frameClients: TframeClient; begin tabClients := TTabSheet.Create(tabPage); tabClients.PageControl := tabPage; tabClients.Caption := FSites[i].moniker; tabClients.Tag := i; frameClients := TframeClient.Create(tabClients); frameClients.Parent := tabClients; frameClients.Align := alClient; frameClients.telnetClient.Host := FSites[i].server; frameClients.telnetClient.OnStatus := telnetClientStatus; frameClients.telnetClient.OnDataAvailable := telnetClientDataAvailable; end; //****************************************************************************** procedure TfrmOctopus.FormCreate(Sender: TObject); var i: integer; begin ImportINI; for i := 0 to FslSiteList.Count - 1 do SetSites(i); end; //****************************************************************************** procedure TfrmOctopus.SendCommand(S: string; telnetToSendTo: TIdTelnet); var i: integer; begin for i := 1 to length(S) do telnetToSendTo.SendCh(S[i]); telnetToSendTo.SendCh(#13); end; //****************************************************************************** procedure TfrmOctopus.Connect(Sender: TObject); var s: string; i, j, k, l: integer; begin for i := 0 to tabPage.PageCount - 1 do begin for j := 0 to tabPage.Pages[i].ControlCount - 1 do if not((tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Connected) then begin (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Connect; l := tabPage.Pages[i].Tag; tabPage.Pages[i].Tag := (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.TelnetThread.ThreadID; sleep(500); s := UPPERCASE(FSites[l].moniker) + 'VISTA'; for k := 1 to length(s) do (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.SendCh(s[k]); (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.SendCh(#13); end; end; end; //****************************************************************************** procedure TfrmOctopus.Disconnect(Sender: TObject); var i, j: integer; begin for i := 0 to tabPage.PageCount - 1 do begin for j := 0 to tabPage.Pages[i].ControlCount - 1 do if ((tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Connected) then begin (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Disconnect; end; end; end; //****************************************************************************** procedure TfrmOctopus.FormDestroy(Sender: TObject); var i, j: integer; begin for i := 0 to tabPage.PageCount - 1 do begin for j := 0 to tabPage.Pages[i].ControlCount - 1 do if not((tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Connected) then begin if ((tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Connected) then (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient.Disconnect; end; end; FslSitelist.Free; FOctopusINI.Free; end; //****************************************************************************** procedure TfrmOctopus.telnetClientDataAvailable(Sender: TIdTelnet; const Buffer: String); const CR = #13; LF = #10; var Start, Stop, iCurrentPID, i, j: Integer; begin iCurrentPID := Sender.TelnetThread.ThreadID; for i := 0 to tabPage.PageCount - 1 do begin if tabPage.Pages[i].Tag = iCurrentPID then // Sync tab begin for j := 0 to tabPage.Pages[i].ControlCount - 1 do begin // Find frame (only control, but for later...) //------------------------------------------------ {This routine comes directly from the ICS TNDEMO code. Thanks to Francois Piette It updates the memo control when we get data} if ((tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Count = 0) then (tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Add(''); Start := 1; Stop := Pos(CR, Buffer); if Stop = 0 then Stop := Length(Buffer) + 1; while Start <= Length(Buffer) do begin (tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Strings[(tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Count - 1] := (tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Strings[(tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Count - 1] + Copy(Buffer, Start, Stop - Start); if Buffer[Stop] = CR then begin (tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Lines.Add(''); {$IFNDEF Linux} SendMessage((tabPage.Pages[i].Controls[j] as TframeClient).memoClient.Handle, WM_KEYDOWN, VK_UP, 1); {$ENDIF} end; Start := Stop + 1; if Start>Length(Buffer) then Break; if Buffer[Start] = LF then Start := Start + 1; Stop := Start; while (Buffer[Stop] <>CR) and (Stop <= Length(Buffer)) do Stop := Stop + 1; Application.ProcessMessages; end; //????MSH if FStageConnect then//------------------------------------------------------- begin // Access & Verify codes //????MSH check for lock out... if (pos('ACCESS CODE:', Buffer)>0) and FSites[i].FContinue then SendCommand(editAccess.Text + #9 + editVerify.Text, (tabPage.Pages[i].Controls[j] as TframeClient).telnetClient); // Signed on? if pos('Not a valid ACCESS CODE/VERIFY CODE pair.', Buffer)> 0 then begin FSites[i].FContinue := FALSE; ShowMessage(FSites[i].moniker + ': Not a valid ACCESS CODE/VERIFY CODE pair.'); end; //????MSH if pos('You last signed on', Buffer)>0 then //????MSH KIDS; end; //------------------------------------------------ end; end; end; end; //****************************************************************************** procedure TfrmOctopus.telnetClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String); begin // Showmessage(ASender.ClassName); //TIdtelnet {SetStatus Bar ???? with multiple connections?} end; //****************************************************************************** end. |