0
votes

Here is my code...

procedure TMainForm.tsConnect(AContext: TIdContext);
var
  s, INstr, adr:string;
  port: Integer;
begin
  with TMyContext(AContext) do
  begin
    Con := Now;
    if (Connection.Socket <> nil) then
      IP :=Connection.Socket.Binding.PeerIP;
    port:=Connection.Socket.Binding.PeerPort;
    s:=IntToStr(Connection.Socket.Binding.PeerPort);
    TIdStack.IncUsage();
    try
      adr:= GStack.HostName;
    finally
      TIdStack.DecUsage;
    end;

    INstr := Connection.IOHandler.ReadLn;
    Nick := INstr;

    if Nick <> '' then
    begin
      memo1.Lines.Add('Opened  <'+Nick + '>  '+adr+' '+IP+':'+s+'      '+DAteTimeToStr(now));
      //SendNicks;
    end else
    begin
      Connection.IOHandler.WriteLn('No Nick provided! Goodbye.');
      Connection.Disconnect;
    end;
  end;
end;

GStack.HostName gives name of my server, how to get client host name?

1

1 Answers

3
votes

Use TIdStack.HostByAddress() to get the client's remote hostname, eg:

adr := GStack.HostByAddress(IP);

With that said, you do not need to call TIdStack.IncUsage() and TIdStack.DecUsage() because TIdTCPServer handles that for you in its constructor and destructor, respectively. But more importanly, your direct access of the TMemo is not thread-safe. Remember that TIdTCPServer is a multi-threaded component. The OnConnect event (and OnDisconnect and OnExecute runs in a worker thread, not the main thread. UI access must be done in the main thread instead.

Try this:

procedure TMainForm.tsConnect(AContext: TIdContext);
var
  INstr, adr: string;
  port: Integer;
begin
  with TMyContext(AContext) do
  begin
    Con := Now;
    IP := Connection.Socket.Binding.PeerIP;
    port := Connection.Socket.Binding.PeerPort;

    adr := GStack.HostByAddress(IP);

    INstr := Connection.IOHandler.ReadLn;
    Nick := INstr;

    if Nick <> '' then
    begin
      TThread.Synchronize(nil,
        procedure
        begin
          memo1.Lines.Add('Opened  <' + Nick + '>  ' + adr + ' ' + IP + ':' + IntToStr(port) + '      ' + DateTimeToStr(Con));
        end
      );
      //SendNicks;
    end else
    begin
      Connection.IOHandler.WriteLn('No Nick provided! Goodbye.');
      Connection.Disconnect;
    end;
  end;
end;

Alternatively:

uses
  ..., IdSync;

type
  TMemoNotify = class(TIdNotify)
  protected
    FMsg: String;
    procedure DoNotify; override;
  end;

procedure TMemoNotify.DoNotify;
begin
  MainForm.Memo1.Lines.Add(FMsg);
end;

procedure TMainForm.tsConnect(AContext: TIdContext);
var
  INstr, adr: string;
  port: Integer;
begin
  with TMyContext(AContext) do
  begin
    Con := Now;
    IP := Connection.Socket.Binding.PeerIP;
    port := Connection.Socket.Binding.PeerPort;

    adr := GStack.HostByAddress(IP);

    INstr := Connection.IOHandler.ReadLn;
    Nick := INstr;

    if Nick <> '' then
    begin
      with TMemoNotify.Create do
      begin
        FMsg := 'Opened  <' + Nick + '>  ' + adr + ' ' + IP + ':' + IntToStr(port) + '      ' + DateTimeToStr(Con);
        Notify;
      end;
      //SendNicks;
    end else
    begin
      Connection.IOHandler.WriteLn('No Nick provided! Goodbye.');
      Connection.Disconnect;
    end;
  end;
end;