Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy: mehrere UDP-Server auf einem Port (https://www.delphipraxis.net/31621-indy-mehrere-udp-server-auf-einem-port.html)

Brüggendiek 11. Okt 2004 21:23


Indy: mehrere UDP-Server auf einem Port
 
Hallo!

Wie man hier sehen kann, schreibe ich zur Zeit ein Programm mit UDP.

Dabei erfuhr ich im verlinkten Thread (danke Basilikum), daß ein Port auch von mehreren Servern gleichzeitig benutzt werden kann.

Da ich Indy 9 verwende, ergibt sich ein Problem:
Beim TCP-Server findet sich auch eine entsprechende Einstellmöglichkeit (Property ReuseSocket). Beim UDP-Server ist das nicht implementiert.

Natürlich könnte ich mich nun in die Tiefen der (etwas chaotischen) Indy-Sources begeben, die Verfahrensweise bei TCP ergründen und auf UDP übertragen.

Nur - warum das Rad zweimal erfinden? Vielleicht hat ja jemand das schon mal implementiert.


Wie kann ich also bei Indy 9 einstellen, daß mehrere UDP-Server auf einem Port arbeiten?


Für Eure Mithilfe bedanke ich mich im Voraus.

Gruß

Dietmar Brüggendiek

Basilikum 11. Okt 2004 22:43

Re: Indy: mehrere UDP-Server auf einem Port
 
leider bietet tidudpserver keine Möglichkeit, um die Option SO_REUSEADDR zum richtigen Zeitpunkt (vor Bind) zu setzen (bei TIdUDPServer.Active:=true wird das vorhandene Binding zerstört, und ein neues initialisiert, wonach natürlich die Option wieder auf dem Default-Value ist).

aber "von Hand" geht's trotzdem:
Delphi-Quellcode:
Uses
  idstack, idstackwindows, idsockethandle;
[...]

Var
  sh : TIdSocketHandle;
  B : Bool;
  Buf : Array[0..127] Of Byte;
begin
  GStack:=TIdStackWindows.CreateStack();

  sh:=TIdSocketHandle.Create(Nil);
  sh.AllocateSocket(SOCK_DGRAM);
  sh.Port:=4444;

  B:=True;
  sh.SetSockOpt(SOL_SOCKET,SO_REUSEADDR,@B,SizeOf(Bool));

  sh.Bind();

  sh.Recv(Buf,SizeOf(Buf),0); // in einen Thread verpacken
end;
Gruss Basilikum

Brüggendiek 12. Okt 2004 20:42

Re: Indy: mehrere UDP-Server auf einem Port
 
Hallo Basilikum!

Erst einmal vielen Dank für die schnelle Antwort.

Verstehe ich das richtig, daß ich mit TidUDPServer nicht arbeiten kann, sondern mir das Ganze mit den Sockets selber erstellen muß?

Falls dem so ist, wearte ich erst mal auf die offizielle Freigabe von Indy 10. Sollte das da auch noch nicht implementiert sein, versuche ich es einzubauen.

Gruß

Dietmar Brüggendiek

Basilikum 12. Okt 2004 22:05

Re: Indy: mehrere UDP-Server auf einem Port
 
Hallo Dietmar

ich habe soeben bemerkt, dass die Methode GetBinding() von TIdUDPServer virtual definiert ist. Dies ermöglicht es, trotzdem die Klasse TIdUDPServer zu verwenden:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdUDPServer, IdStackConsts, IdSocketHandle, StdCtrls;

type
  TUDPServer = Class(TIdUDPServer)
  Protected
    function GetBinding: TIdSocketHandle; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    _UDPServer : TUDPServer;
    { Private declarations }
  public
    { Public declarations }
    procedure UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TUDPServer.GetBinding: TIdSocketHandle;
var
  i: integer;
begin
  if not Assigned(FCurrentBinding) then
  begin
    if Bindings.Count < 1 then begin
      Bindings.Add;
    end;
    for i := 0 to Bindings.Count - 1 do begin
      Bindings[i].AllocateSocket(Id_SOCK_DGRAM);
      Bindings[i].SetSockOpt(Id_SOL_SOCKET,Id_SO_REUSEADDR,@Id_SO_True,SizeOf(Bool)); // Bis auf diese Zeile ist alles kopiert von TIdUDPServer
      Bindings[i].Bind;
    end;
    FCurrentBinding := Bindings[0];
    FListenerThread := TIdUDPListenerThread.Create(BufferSize, Self);
    FListenerThread.Start;
    BroadcastEnabledChanged;
  end;
  Result := FCurrentBinding;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Dies ist nur notwendig, da ich die Indy-Palette nicht installiert habe.... ansonsten per OI
  _UDPServer:=TUDPServer.Create(Self);

  _UDPServer.DefaultPort:=4444;
  _UDPServer.Active:=True;

  _UDPServer.OnUDPRead:=UDPRead;
end;

procedure TForm1.UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
Var
  S : String;
Begin
  SetLength(S,4);
  AData.Read(S[1],4);

  Caption:=S;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  _UDPServer.Broadcast('test',4444);
end;

end.
Gruss Basilikum

Brüggendiek 13. Okt 2004 21:53

Re: Indy: mehrere UDP-Server auf einem Port
 
Hallo Basilikum!

Herzlichen Dank für den Code. Damit funktioniert das so, wie ich mir das vorgestellt hatte.

Es ist mir allerdings unverständlich, wieso das bei den Indys nicht vorgesehen ist. Da werde ich mal nachfragen müssen.


Gruß

Dietmar Brüggendiek


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz