Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Dateien an PC's senden und empfangen (https://www.delphipraxis.net/143513-dateien-pcs-senden-und-empfangen.html)

Urmel81 17. Nov 2009 13:32


Dateien an PC's senden und empfangen
 
Hallo Zusammen,

ich versuche mit Delphi 5 in einer Konsolen Anwendung einen Client und einen Server zu programmieren um dann zwischen Server und Client Daten auszutauschen. Nach ein paar Recherchen hatte ich die Idee dafür Sockets zu verwenden, aber irgendwie gibt es dazu keine wirklich gute Beschreibung im Internet wie man sowas auf Konsolenebene anstellt. Ich kenne mich zwar einigermaßen mit Sockets aus, aber Delphi ist für mich noch Neuland.

Vielleicht hat jemand eine Idee dazu, oder kennt einen hilfreichen Link.

Besten Dank schonmal im Voraus.

RWarnecke 17. Nov 2009 13:44

Re: Dateien an PC's senden und empfangen
 
TTCPServer & TTCPClient von den Indy's. Damit kannst Du Daten zwischen Rechner hin und her schicken.

uoeb7gp 17. Nov 2009 14:13

Re: Dateien an PC's senden und empfangen
 
Hallo, kuck mal da!

http://www.delphi-treff.de/tutorials...ets-mit-winapi

Was brauchst den genau?

Synchrone oder Asynchrone Übertragung?

Was brauchst an Performance (Max Anzahl der Clients, Datenvollumen etc.) ?

uoeb7gp 17. Nov 2009 14:33

Re: Dateien an PC's senden und empfangen
 
Also eine Consolen Application für einen asynchronen Socket kann in etwa so aufgebaut werden.


Delphi-Quellcode:
program AsyncClientConsole;

  {$APPTYPE CONSOLE}

uses
  windows,
  SysUtils,
  messages,
  uConsoleClass in 'uConsoleClass.pas';

function MainWndProc(ahWnd: HWND; auMsg: Integer; wp: WPARAM;
  lp : LPARAM): Integer; stdcall; forward;

const
  WM_DATA     = WM_USER + 1;
  WM_CONNECTED = WM_USER + 2;
  WM_ERROR    = WM_USER + 3;

var
  Terminated   : Boolean;
  hWndMain     : HWND;

  TADAMainWindowClass : TWndClass = (style: 0; lpfnWndProc: @MainWndProc;
    cbClsExtra: 0; cbWndExtra: 0; hInstance: 0; hIcon: 0; hCursor: 0;
    hbrBackground: 0; lpszMenuName: nil; lpszClassName: 'MyConsoleMainWindowClass'
    );

procedure WMOnConnected(wp, lp: DWORD);
begin
  writeln('WMOnConnected : ' + PChar(wp));
end;

procedure WMOnData(wp, lp: DWORD);
begin
  writeln(PChar(wp));
  writeln(inttostr(lp));
end;

procedure WMOnError(wp, lp: DWORD);
begin
  writeln('WMOnECSError    : ' + PChar(wp));
end;

function MainWndProc(ahWnd: HWND; auMsg: Integer; wp: WPARAM;
  lp: LPARAM): Integer; stdcall;
begin
  Result := 0;

  if auMsg = WM_DATA then
    WMOnData(wp, lp)
  else if auMsg = WM_CONNECTED then
    WMOnConnected(wp, lp)
  else if auMsg = WM_ERROR then
    WMOnError(wp, lp)
  else if auMsg = WM_CLOSE then
    DestroyWindow(ahWnd)
  else
    Result := DefWindowProc(ahWnd, auMsg, wp, lp);

end;

function InitAplication : Boolean;
begin
  Result := FALSE;

  if Windows.RegisterClass(TADAMainWindowClass) = 0 then Exit;

  hWndMain := CreateWindowEx(WS_EX_TOOLWINDOW, TADAMainWindowClass.lpszClassName,
    '', WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);

  if hWndMain = 0 then Exit;

  (******** Hier nun Socket Connection durchführen und
     Messaging mit Windowsmessages und oder mit Callback, je nach Geschmack
  ********)

  Result := TRUE;
end;


procedure CleanupAplication;
begin
  if hWndMain <> 0 then begin
    DestroyWindow(hWndMain);
    hWndMain := 0;
  end;
end;

procedure RunAplication;
var
  MsgRec : TMsg;
begin
  while GetMessage(MsgRec, 0, 0, 0) do begin
    TranslateMessage(MsgRec);
    DispatchMessage(MsgRec)
  end;
  Terminated := TRUE;
end;

begin
  InitAplication;
  try
    RunAplication;
  finally
    CleanupAplication;
  end;
end.

Urmel81 18. Nov 2009 08:48

Re: Dateien an PC's senden und empfangen
 
Vielen Dank für die schnellen Antworten und dem Beispielprogramm. werd das gleich mal ausprobieren. :-)

also ich will am ende quasi von einer zentralen stelle an mehrere clients signale schicken und deren antwort empfangen und auswerten. wie so eine art telefonanruf. ich schicke ein signal(wähle die nummer der person die ich erreichen will), es klingelt bei dem anderen, dann nimmt er ab und ich bekomme z.B. das signal "Hallo" zurück. die verbindung muss nur so lange bestehen, bis die antwort eingegangen ist, danach kann sie sofort beendet werden.
die anzahl der clients kann ich noch nicht genau sagen, aber da die verbindungen eh schnellstmöglich wieder getrennt werden ist sicher keine allzu große zahl nötig.
achso, noch zum datenvolumen. also ich denke das max ein paar 100 kbyte ausreichen sollten. das grösste was dabei übertragen werden könnte wäre eine textdatei in der eigentlich so gut wie nichts drin stehen muss. ansonsten werden ja nur signale übertragen und die sind ja bei weitem nicht so groß.

uoeb7gp 18. Nov 2009 09:33

Re: Dateien an PC's senden und empfangen
 
Ok, alles fix und fertig!

Schön gekapselt in DLL's (Client-Server) Synchroner und Asynchroner Transport.

Hochlasttauglich (Async ist mit 10000 Clients) getestet.

Sync skaliert excellent (mit 2 X Quad-Cores Xeons) getestet.

http://www.delphipraxis.net/download.php?id=41481
http://www.delphipraxis.net/download.php?id=41480

Have a lot of fun!

Urmel81 18. Nov 2009 09:57

Re: Dateien an PC's senden und empfangen
 
wow

ich hoffe ich steig da jemals durch was du hier gebastelt hast.

wie gesagt, bin in delphi noch anfänger und wäre mit einer simplen "stino"-lösung die man leicht nachvollziehen kann auch zufrieden gewesen ;-)

ich danke dir aber auf jedenfall für deine mühen und werd mich mal ans "lesen und verstehen" ran machen :-)

himitsu 18. Nov 2009 10:11

Re: Dateien an PC's senden und empfangen
 
Ich hab meinen ersten/aktuellen Server in seinen Grundzügen quasi so gestaltet:
Delphi-Quellcode:
Program HiddenServer;

{$APPTYPE CONSOLE}

{$R *.res}

Uses Windows, SysUtils, Classes, Forms, Graphics, IdContext,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer;

Type THandler = Class(TComponent)
  Public
    Constructor Create(AOwner: TComponent);
    Destructor Destroy; Override;
    Procedure ServerConnect(Context: TIdContext);
    Procedure ServerExecute(Context: TIdContext);
    Procedure ServerDisconnect(Context: TIdContext);
    Procedure ServerStatus(Sender: TObject; Const Status: TIdStatus; Const StatusText: String);
    ...
  End;

Constructor THandler.Create(AOwner: TComponent);
  Begin
    Inherited;
    ...
  End;

Destructor THandler.Destroy;
  Begin
    ...
    Inherited;
  End;

Procedure THandler.ServerConnect(Context: TIdContext);
  Begin
    WriteLn('#Connect: ', Context.Binding.PeerIP, ':', Context.Binding.PeerPort);
    ...
  End;

Procedure THandler.ServerExecute(Context: TIdContext);
  Begin
    ...
    If (beenden) Then Application.Terminate;
    ...
  End;

Procedure THandler.ServerDisconnect(Context: TIdContext);
  Begin
    WriteLn('#Disconnect: ', Context.Binding.PeerIP, ':', Context.Binding.PeerPort);
    ...
  End;

Procedure THandler.ServerStatus(Sender: TObject; Const Status: TIdStatus; Const StatusText: String);
  Const X: Array[TIdStatus] of String = ('haResolving', 'hsConnecting', 'hsConnected',
      'hsDisconnecting', 'hsDisconnected', 'hsStatusText', 'ftpTransfer', 'ftpReady', 'ftpAborted');

  Begin
    WriteLn('#State (', X[Status], '): ', StatusText);
  End;

Var Handler: THandler;
  Server:   TIdTCPServer;

Function HandlerRoutine(CtrlType: LongWord): LongBool; StdCall;
  Begin
    FreeAndNil(Server);
    FreeAndNil(Handler);
    Result := False;
  End;

Begin
  SetConsoleCtrlHandler(@HandlerRoutine, True);
  Try
    Application.Initialize;
    Handler := THandler.Create(Application);
    Try
      Server := TIdTCPServer.Create(Handler);
      Server.OnConnect   := Handler.ServerConnect;
      Server.OnExecute   := Handler.ServerExecute;
      Server.OnDisconnect := Handler.ServerDisconnect;
      Server.OnStatus    := Handler.ServerStatus;
      Server.DefaultPort := 50000;
      Server.Active      := True;
      Try
        Repeat
          Application.ProcessMessages;
          Sleep(10);
        Until Application.Terminated;
      Finally
        FreeAndNil(Server);
      End;
    Finally
      FreeAndNil(Handler);
    End;
  Except
    On E:Exception do WriteLn(E.ClassName, ': ', E.Message);
  End;
End.
Wobei man den Server (TIdTCPServer, Sockets oder was auch immer) auch in den THandler hineinverlagern könnte, also diesen in .Create erstellen und in .Destroy freigeben.

Ist im Grunde wie bei uoeb7gp (#4), nur daß dort die Verwaltung des Nachrichtenfensters und die Nachrichtenbehandlung Application überlassen und für die Verbidung direkt eine der fertigen Internetkomponenten verwendet wird.

PS: die HandlerRoutine ist für denn Fall, daß das Konsolenfenster über [X] geschlossen wird, also damit auch in diesem Fall alles ordnungsgemäß beendet wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:40 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