Question

I need to write a Delphi 2009 application, which reads data from a socket. To do this, I need to write an event handler for the TIdTCPServer.OnExecute event.

I found lots of examples for implementing this in GUI applications, but I need to do it in a console application (without any windows).

How should I modify the code below in order to add an event handler (attach it to TCPServer), which prints every received message into the debug output?

unit ReceivingThreadUnit;

interface

uses
  Classes,
  IdTCPServer,
  IdSocketHandle,

  SysUtils,
  Windows;

type
  ReceivingThread = class(TThread)
    private
      TCPServer: TIdTCPServer;
    public
      procedure Run();

  end;

implementation

procedure ReceivingThread.Run();
var
  Bindings: TIdSocketHandles;
begin
  TCPServer := TIdTCPServer.Create(nil);

  //setup and start TCPServer
  Bindings := TIdSocketHandles.Create(TCPServer);
  try
    with Bindings.Add do
    begin
      IP := '127.0.0.1';
      Port := 9998;
    end;
    try
      TCPServer.Bindings:=Bindings;
      // Here I want to attach TCPServer to an OnExecute event handler
      TCPServer.Active:=True;
    except on E:Exception do
      OutputDebugString(PChar(E.ToString));
    end;
  finally
    Bindings.Free;
    TCPServer.Free;
  end;
  TCPServer.Active := true;
end;

end.
Was it helpful?

Solution 2

You need to add an event handler to your class. And then connect it up:

TCPServer.OnExecute := Self.ExecuteHandler;

OTHER TIPS

As David said (but did not fully show), you need to declare a method in your thread class and then assign it to the OnExecute event.

On a side note, you should not be creating a TIdSocketHandles collection manually. Call Add() on the existing TIdTCPServer.Bindings collection instead.

Try this:

unit ReceivingThreadUnit;

interface

uses
  Classes,
  IdTCPServer,
  IdSocketHandle,
  IdContext,

  SysUtils,
  Windows;

type
  ReceivingThread = class(TThread)
  private
    TCPServer: TIdTCPServer;
    procedure ExecuteHandler(AContext: TIdContext);
  public
    procedure Run;
  end;

implementation

procedure ReceivingThread.ExecuteHandler(AContext: TIdContext);
begin
  //...
end;

procedure ReceivingThread.Run;
begin
  //setup and start TCPServer
  TCPServer := TIdTCPServer.Create(nil);
  try
    with TCPServer.Bindings.Add do
    begin
      IP := '127.0.0.1';
      Port := 9998;
    end;
    TCPServer.OnExecute := ExecuteHandler;
    try
      TCPServer.Active := True;
    except
      on E: Exception do
        OutputDebugString(PChar(E.ToString));
    end;
    while not Terminated do
      Sleep(1000);
    TCPServer.Active := False;
  finally
    TCPServer.Free;
  end;
end;

end.

With that said, your receiveing thread is actually pretty redundant since TIdTCPServer is already multi-threaded, so you could alternatively just eliminate the thread class altogether:

program MyApp;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Classes,
  IdTCPServer,
  IdSocketHandle,
  IdContext,

  SysUtils,
  Windows;

type
  TCPServerEvents = class
  public
    class procedure ExecuteHandler(AContext: TIdContext);
  end;

class procedure TCPServerEvents.ExecuteHandler(AContext: TIdContext);
begin
  //...
end;

var
  TCPServer: TIdTCPServer;
begin
  //setup and start TCPServer
  TCPServer := TIdTCPServer.Create(nil);
  try
    with TCPServer.Bindings.Add do
    begin
      IP := '127.0.0.1';
      Port := 9998;
    end;

    TCPServer.OnExecute := TCPServerEvents.ExecuteHandler;

    try
      TCPServer.Active := True;
    except
      on E: Exception do
        OutputDebugString(PChar(E.ToString));
    end;

    while (not stop condition) do
      Sleep(1000);

    TCPServer.Active := False;
  finally
    TCPServer.Free;
  end;
end.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top