Avatar billede delphi Nybegynder
24. oktober 2001 - 11:22 Der er 1 kommentar og
1 løsning

Indy server application: Hvordan kan jeg se hvilket client der har sendt en given \"command\"?

Nedenstående code er en ret simpel INDY (ver 9.02) TCP server application.  Server componenten i denne application kører med CommandHandlers, to styk, der hver har deres OnCommand-events. 
Når en client, fx. en Telnet client, har logget på og senere sender en af de to commands disse handlers reagerer på, så bliver den pågældende metode udført og som parameter overføres \"ASender: TIdCommand\". 
Hvorledes kan jeg udfra denne parameter se hvilken client der er tale om?  Fx. dens IP adresse eller lignende?

Fidusen er, at jeg vil lave en application, hvor de enkelte clienter connecter og dernæst fortæller serveren at de har en eller anden \'evne\' - fx. at de råder over et digitalt output.
Senere skal man så kunne sende en command fra serveren til clienten om at \'bruge sin evne\' - fx. sætte den digitale udgang.
Serveren skal derfor dynamisk opbygge en liste over \'evner\' i forhold til disses fysiske placering (ejer client) og er derfor nødt til at kunne identificere client\' inputtene på en eller anden måde.

I nedenstående code viser kommentarene hvor der skal ske et eller andet.

Peter


unit fmFTPServerMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPServer, IdFTPServer, StdCtrls,
  IdUDPBase, IdUDPServer, IdTrivialFTPServer, ComCtrls;

type
  TForm1 = class(TForm)
    IdTCPServer1: TIdTCPServer;
    Memo1: TMemo;
    StatusBar1: TStatusBar;
    procedure FormShow(Sender: TObject);
    procedure IdServer1Connect(AThread: TIdPeerThread);
    procedure IdServer1Disconnect(AThread: TIdPeerThread);
    procedure IdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
    procedure IdTCPServer1CommandHandlers1Command(ASender: TIdCommand);
  private
    { Private declarations }
    ConnectionCount : Integer;
  public
    { Public declarations }
    Function KnownCommands : TStrings;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  ConnectionCount := 0;

  Memo1.Lines.Assign(KnownCommands);
  Memo1.Lines.Insert(0, \'INSTRUCTIONS:\');
  Memo1.Lines.Insert(1, \'=============\');
  Memo1.Lines.Insert(2, \'Use Telnet to connect to port 21.\');
  Memo1.Lines.Insert(3, \'Known commands:\');
  Memo1.Lines.Add(\'\');

  StatusBar1.SimpleText  := \'Connection count: \' + IntToStr(ConnectionCount);
end;

procedure TForm1.IdServer1Connect(AThread: TIdPeerThread);
begin
  Inc(ConnectionCount);
  StatusBar1.SimpleText  := \'Connection count: \' + IntToStr(ConnectionCount);
end;

procedure TForm1.IdServer1Disconnect(AThread: TIdPeerThread);
begin
  Dec(ConnectionCount);
  StatusBar1.SimpleText  := \'Connection count: \' + IntToStr(ConnectionCount);
end;

function TForm1.KnownCommands: TStrings;
Var
  t : Integer;
begin
  Result := TStringList.Create;
  For t := 0 To idTCPServer1.CommandHandlers.Count- 1 Do
    Result.Add(IdTCPServer1.CommandHandlers.Items[t].Command)
end;


// Commandhandlers.
procedure TForm1.IdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
Var
  t : Integer;
begin
  //
  // NB!  HER!  Hvilken client, fx. IP-adresse, sendte denne command?
  //
  For t := 0 To ASender.Params.Count-1 Do
    Memo1.Lines.Add(\'Received: \'+ASender.Params[t]);
end;

procedure TForm1.IdTCPServer1CommandHandlers1Command(ASender: TIdCommand);
Var
  t : Integer;
begin
  //
  // NB!  HER!  Hvilken client, fx. IP-adresse, sendte denne command?
  //
  For t := 0 To ASender.Params.Count-1 Do
    Memo1.Lines.Add(\'Received: \'+ASender.Params[t]);
end;

end.
Avatar billede delphi Nybegynder
24. oktober 2001 - 16:13 #1
Jeg har løst problemet selv.

Svar følger....

Peter
Avatar billede delphi Nybegynder
24. oktober 2001 - 16:20 #2
I nedenstående lille testprogram gør jeg følgende:

type
  TForm1 = class(TForm)
    ...
  private
    { Private declarations }
    FirstConnection : Integer;
  public
  end;

En Integer benyttes til gemme \'noget\' der specifikt kendetegner den først client der connecter.

Initializing FirstConnection

procedure TForm1.FormCreate(Sender: TObject);
begin
  ...
  FirstConnection := 0;
end;

Hver gang en client connecter kaldes:

procedure TForm1.IdServer1Connect(AThread: TIdPeerThread);
begin
  If FirstConnection = 0 Then
    FirstConnection := AThread.ThreadID;
end;

Hvis det er første connection der kommer, så gem dens ThreadID som identifikation. 
Hvis jeg kunne aflæse IP adressen på Clienten, så kunne den givetvis også bruges.  Hvordan kan man mon få den?  - Det vil jeg gerne vide, så der er point til den der har svaret.



Hver gang der kommer en command, af den rigtige type, fra en tilsluttet client, så køres denne metode:

// Commandhandlers.
procedure TForm1.IdTCPServer1CommandHandlers1Command(ASender: TIdCommand);
begin
  If ASender.Thread.ThreadID = FirstConnection Then
    Begin
      Memo1.Lines.Add(\'TEST Received from first connection\');
      Asender.Reply.SetReply(200, \'Hello first connection \'+
                            IntToStr(ASender.Thread.ThreadID));
    End
  Else
    Begin
      Memo1.Lines.Add(\'TEST Received from some other connection\');
      Asender.Reply.SetReply(200, \'Hello some other connection \'+
                            IntToStr(ASender.Thread.ThreadID));
    End;
end;

Jeg checkker om clientens ThreadID er det som jeg gemte fra første connection - og i såfald sender jeg en note om det.  Alle andre clients får en anden std. reply.

Peter
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester