StreamServer/Client

Tags:    delphi
Skrevet af Bruger #236 @ 17.06.2001
Brug af StreamServer/Client

Jeg skrev denne artikel, da jeg startede projektet "New-Life" (En Server/Klient-del til Half-Life). Programmet skulle kunne chatte, Sende ens personlige "Logo", navn og sidst men ikke mindst... Starte Counter-Strike. Chatten var for mig det sværeste kapitel i denne programmering. Så det første jeg prøvede med var TMailSlot men desværre virkede det ikke efter hensigten, fordi man ikke kunne skrive modtagne meddelelser i en Memo. Nå tænkte jeg... Så må vi vel ty til hårdere metoder. Og jeg ledte alle Demoer i Delphi-mappen igennem, og fandt til sidst hvad jeg skulle bruge... Chat-eksemplet vare et godt eksempel og så Stream-serveren til at sende billeder. Men denne artikel har jeg tænkt at dele op i to, og jeg startede fra den mest spændene ende... Filsendingen. Jeg startede med at kigge lidt på hvordan henholdsvis klient- og server-programmet virkede. Jeg opdagede at det var Serveren der modtog meddelelser (i Stream) og klienten der sendte (Sjovt nok tænkte jeg, men nu ikke mere om det).

Det eksempel jeg her vil vise jer er hvordan at man ved hjælp af et Server og et Klient-program, kan Sende filer. Jeg besluttede at det var Serveren der skulle sende og klienten der skulle oplagre. Da jeg tit sender ZIP-filer over netværk vil jeg her i eksemplet vise jer hvordan man (!surprise!) sender Zip-filer over Server-Klient-metoden.

Klienten

Koden først, jeg forklarer bagefter:
unit frmKlient;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Psock, NMSTRM;

type
  TForm1 = class(TForm)
    NMStrmServ1: TNMStrmServ;
    Label1: TLabel;
    SaveDialog: TSaveDialog;
    procedure NMStrmServ1ClientContact(Sender: TObject);
    procedure NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
      strm: TStream);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.NMStrmServ1ClientContact(Sender: TObject);
begin
  NMStrmServ1.ReportLevel := Status_Basic;
  // her sætter vi Time-outen til 90 sekunder
  NMStrmServ1.TimeOut := 90000;
end;

procedure TForm1.NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
  strm: TStream);
var
  MyFStream: TFileStream;
begin
  // her sletter vi vores "tmp"-fil hvis den eksisterer
  If FileExists('.\\tmp.zip') then DeleteFile('.\\tmp.zip');
  // her laver vi så en ny fil ud af de indformationer serveren sendte
  MyFStream := TFileStream.Create('.\\tmp.zip', fmCreate);
  try
    MyFStream.CopyFrom(strm, strm.size);
  finally
    MYFStream.Free;
  end;
  // En ting der manglede var muligheden for at gemme så den har jeg lavet her:
  if SAveDialog.Execute then
  begin
    CopyFile('.\\tmp.zip', PChar(SaveDialog.Filename), true);
  end;
end;

end.
Vi går bare direkte til procedurene: Når NMStrmServ1 får kontakt til en klient sætter den Time-outen til 90 sekunder, så ifølge mig (I må gerne rette mig) stopper serveren efter 90 sekunder hvis der ikke sker noget.

Og den anden procedure vi har brugt er at definere hvad der skal ske hvis NMStrmServ1 modtager en meddelelse. Hvis du kigger lidt på de kommentarer jeg har skrevet så vil du forstå det første. Men videre har jeg sadt en SaveDialog ind til at gemme ZIP-filen med, og jeg bruger her CopyFile- metoden. CopyFile metoden kopierer simpelthend bare filen ligesom Windows ville gøre det.

Serveren

Koden først, jeg forklarer bagefter:
unit frmServer;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, Psock, NMSTRM;

type
  TServer = class(TForm)
    NMStrm1: TNMStrm;
    Label1: TLabel;
    StatusBar1: TStatusBar;
    Button1: TButton;
    Label2: TLabel;
    Edit2: TEdit;
    OpenDialog: TOpenDialog;
    procedure NMStrm1PacketSent(Sender: TObject);
    procedure NMStrm1MessageSent(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Server: TServer;

implementation

{$R *.DFM}

procedure TServer.NMStrm1PacketSent(Sender: TObject);
begin
  // viser forsendelses-statusen
  StatusBar1.SimpleText := IntToStr(NMStrm1.BytesSent)+' af '+IntToStr(NMStrm1.BytesTotal)+' sendt';
end;

procedure TServer.NMStrm1MessageSent(Sender: TObject);
begin
  // viser en meddelesesboks hvis filen blev sendt
  ShowMessage('Filen er blevet sendt til ' + NMStrm1.Host);
end;

procedure TServer.Button1Click(Sender: TObject);
var
  MyFStream: TFileStream;
begin
  // her vælger vi så hvilken fil vi vil sende
  If OpenDialog.Execute then
  Begin
    // Her får vi fadt på IP-en til klienten
    NMStrm1.Host := Edit2.Text;
    NMStrm1.FromName := 'Server 1';
    // her finder vi så filen der skal sendes
    MyFStream := TFileStream.Create(OpenDialog.FileName, fmOpenRead);
    try
      NMStrm1.PostIt(MyFStream);
    finally
      MyFStream.Free;
    end;
  end;
end;

end.
Hvis du kigger lidt på de to første procedurer så kan du nok selv gennemskue dem. Men hvis du kigger på Button1's procedure (Button1s caption er sat til Send fil) kan du se at det første der sker er at vi åbner en Open- Dialog, og hvis der bliver trykket OK så vil sendingen begynde, Edit2 er IP-en på Klienten og den er normalt sat til 127.0.0.1 hvis du bare tester den på en computer. Jeg har desværre ikke haft mulighed for at teste dette over lokalt netværk eller internet, men det burde virke i praksis.


Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (2)

User
Bruger #3807 @ 11.06.03 21:19
Hvor finder du de server client komponenter i delphi 7
User
Bruger #5097 @ 05.03.05 21:31
Forstår heller ikke hvad det er....
Du skal være logget ind for at skrive en kommentar.
t