× Aktuálně z oboru

Vychází Game Ready ovladače pro Far Cry 5 [ clanek/2018040603-vychazi-game-ready-ovladace-pro-far-cry-5/ ]
Celá zprávička [ clanek/2018040603-vychazi-game-ready-ovladace-pro-far-cry-5/ ]

Posílání souborů po síti

[ http://programujte.com/profil/20356-lubos-uhliarik/ ]Google [ ?rel=author ]       [ http://programujte.com/profil/118-zdenek-lehocky/ ]Google [ ?rel=author ]       13. 3. 2007       24 305×

V tomto díle si ukážeme, jak poslat soubor po počítačové síti.

V jednom z minulých dílu jsme se učili udělat chat v Delphi za pomocí komponent ServerSocket a ClientSocket. Jestliže nemáte žádné zkušenosti s těmito komponentami, doporučoval bych článek si přečíst. Začnu asi trochou teorie, jak by nám to posílání mělo fungovat. Nejprve si na klientském počítači vybereme soubor, který budeme chtít odeslat. Po tom, co si soubor vybereme, připojíme se k našemu serveru a odešleme mu název souboru a jeho velikost. Jakmile budou základní informace o souboru odeslané, stačí už jen odeslat soubor. Obrázek klienta:

Ještě je tam komponenta OpenDialog. U Button2 a Button3 nastavte Enabled na False. A teď zdrojový kód:

….
  private
    Soubor_Stream:TFileStream; //vytvoření proměnné, přes kterou budeme odesílat soubor
  public
….

Další pomocné proměnné:

var
  Form1: TForm1;
  soubor: string; //uložení filename souboru
  velikost :int64; //velikost souboru

Když stiskneme tlačítko Otevři:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then begin
    if Trim(OpenDialog1.FileName) <> "" then begin
       if fileexists(OpenDialog1.FileName) then begin
          soubor := ExtractFileName(OpenDialog1.FileName); //nastavíme název souboru
          Label2.Caption := soubor; 
          Soubor_Stream := TFileStream.Create(soubor,fmOpenRead);// otevřeme soubor a uložíme do streamu
          Button2.enabled := True;
       end;
    end;
  end;
end;

Tlačítko Připojit:

procedure TForm1.Button2Click(Sender: TObject);
begin
  ClientSocket1.ClientType := ctNonBlocking;
  ClientSocket1.Port := 123456; // nastavíme port
  ClientSocket1.Address := Edit1.Text; // nastavíme IP adresu
  ClientSocket1.Active := True;
end;

Když se připojíme:

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Button3.enabled := True;
end;

Když se odpojíme:

procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Button1.Enabled := True;
  Button2.Enabled := False;
  Button3.Enabled := False;
end;

Jestliže nám přichází příkazy ze serveru, tak se na ně podíváme:

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  zprava:string; //pomocná proměnná
begin
  zprava := socket.ReceiveText; //přiřadíme text, který přišel
  if zprava = "NAME ??" then begin //jestli je zpráva „NAME ??“
    socket.SendText("NAME = "+ label2.Caption); //odešleme jméno souboru
  end;

  If zprava = "SIZE ??" then begin //jestli je zpráva „SIZE ??“
    socket.SendText("SIZE = " + IntToStr(Soubor_Stream.Size)); //odešleme velikost souboru
  end;
end;

A poslední tlačítko – Odeslat:

procedure TForm1.Button3Click(Sender: TObject);
begin
     ClientSocket1.Socket.SendStream(Soubor_Stream);
end;

Tímto jsme vlastně odeslali soubor na server. Teď si ukážeme, jak server vypadá:

Snad jedinou použitou komponentou je tam memo. U něj si nastavme vlastnost ReadOnly na True. Zdrojový kód serveru:

Proměnné:

var
  Form1: TForm1;
  FStream: TFileStream; //proměnná na ukládání souboru
  cekam_na_jmeno, cekam_na_velikost:boolean; //pomocné proměnné 
  jmenoSouboru:string; //jméno souboru
  velikost_soub:int64; //velikost souboru

Po vytvoření formuláře:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ServerSocket1.ServerType := stNonBlocking; //spojení bude neblokující
  ServerSocket1.Port := 123456; //port
  ServerSocket1.Active := True; //zapneme server
  cekam_na_jmeno := false; //inicializace proměnných
  cekam_na_velikost := true; //inicializace proměnných
end;

Když se zapne server:

procedure TForm1.ServerSocket1Listen(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Memo1.Lines.Add("Naslouchám......."); // server ohlásí, že je připraven
end;

Při připojení klienta:

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Memo1.Lines.Add("Připojen: "+socket.LocalHost+"("+socket.RemoteAddress+")"); //vložíme do mema informace, kdo se k nám připojil
  socket.SendText("NAME ??"); //odešleme dotaz
  cekam_na_jmeno := true; //změníme pomocnou proměnou
end;

A teď asi nejdelší a nejsložitější část (když přijdou nějaká data na server):

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  velikost: integer; //velikost příchozích dat
  buffer: Pointer; //pomocný ukazatel
  zprava:string; //pomocná proměnná k zjištění, co přišlo za příkaz
begin
     if cekam_na_jmeno then begin// jestliže čekáme na jméno souboru
       zprava := Socket.ReceiveText; //do proměnné vložíme, co nám přišlo
       if leftStr(zprava,7) = "NAME = " then begin //jestliže to bude jméno, pak…
         jmenoSouboru := rightStr(zprava,Length(zprava)-7);//"vycucneme" název souboru z řetězce
         FStream := TFileStream.Create(jmenoSouboru,fmCreate or fmShareDenyWrite); //vytvoříme stream, kam se budou zapisovat části souboru
         cekam_na_jmeno := false;
         cekam_na_velikost := true;
         socket.SendText("SIZE ??"); //odešleme příkaz
         Memo1.Lines.Add("Jméno souboru: "+jmenosouboru);  // vypíšeme do mema jméno souboru
       end;
     end;

     if cekam_na_velikost then begin // jestliže čekáme na velikost souboru
       zprava := Socket.ReceiveText; //do proměnné vložíme, co nám přišlo
       if leftStr(zprava,7) = "SIZE = " then begin //jestliže zpráva bude začínat na „SIZE = “
         velikost_soub := StrToInt(RightStr(zprava,Length(zprava)-7)); //vycucneme velikost souboru
         cekam_na_velikost := false; //přestaneme čekat na velikost souboru
         Memo1.Lines.Add("Velikost souboru: "+IntToStr(velikost_soub)+" b");
       end;
     end;

     velikost := socket.ReceiveLength;//kolik dat jsme příjali
     GetMem(buffer,velikost);//alokujeme paměť

     try
       socket.ReceiveBuf(buffer^,velikost); //do bufferu uložíme to, co nám přišlo
       FStream.Write(buffer^, velikost); // a zapíšeme do souboru
     finally
       FreeMem(buffer); //uvolníme paměť
     end;

     if velikost_soub = FStream.Size then begin
        Memo1.Lines.Add("Posílání souboru ukončeno");
        ServerSocket1.Active := false; // vypneme server a tím docílíme odpojení klienta
        Memo1.Lines.Add("Server neaktivní"); //zapíšeme do mema
        ServerSocket1.Active := true;// zapneme server
        FStream.Free;// uvolníme proměnnou
     end;

end;

Toto je celé. Snažil jsem se popsat vše, co by mohlo být nesrozumitelné, ale myslím si, že teď to snad pochopí i průměrně zkušený programátor v Delphi.

Prosím, nepište do komentářů, že například tento kód není správný:

socket.ReceiveBuf(buffer^,velikost); //do bufferu uložíme to, co nám přišlo

Mělo tam být, že do pointeru buffer se uloží adresa na data, ale chtěl jsem to udělat tak, aby to opravdu pochopil skoro každý. To je pro tento díl vše.


Článek stažen z webu Programujte.com [ http://programujte.com/clanek/2007031201-posilani-souboru-po-siti/ ].