Delphi

Síťové - LAN - aplikace

Vážím si programátorů aplikací pro síť. V DOSu vytvořit takové programy bez přístupu k informacím bylo nemožné. Potom, co se mi dostaly do ruky Delphi 2.0, pokusil jsem se proniknout do tvorby těchto programů v 32bitových operačních systémech od Microsoftu. Po dlouhém přehrabování v helpech jsem zjistil, že síťovou komunikaci mezi dvěma počítači můžeme vytvořit:

  • na úrovni síťových protokolů (je to dost maso a jen pro machry)
  • pomocí "pojmenované roury - Named Pipe" (je to obousměrná komunikace, služby jsou ale implementovány jen ve Windows NT)
  • pomocí mailslotů (pro 32bitové OS, tedy WinNT a Win95)

Nejvýhodnější jsou asi pro programátora mailsloty. Nevýhoda je, že se jedná o jednosměrnou komunikaci. Na jedné straně je vysílající program, který směřuje zprávy buď určité aplikaci, nějakému počítači nebo celé doméně (Microsoft to přirovnává k vysílání kabelové televize). Vysílání je realizováno jako zápis do souboru, ten ale ve skutečnosti neexistuje. Jméno tohoto souboru, tedy jméno slotu, se určuje následovně:

  • \\.\mailslot\jménoslotu pro zasílání na lokální mailslot (tedy na tento počítač)
  • \\jménopočítače\mailslot\jménoslotu pro zasílání dat určitému počítači
  • \\jménodomény\mailslot\jménoslotu pro zasílání dat celé doméně (s určitým jménem)
  • \\*\mailslot\jménoslotu pro zasílání dat primární doméně

Velikost předávaných zpráv je omezena (400B pro doménu, jinak max 64kB). Zápis je možné realizovat například následující funkcí:

function PosliNaSlot (Slovo:PChar):boolean;
var fResult:Boolean; hFile:THandle;
    cbWritten:DWord;
begin
 PosliNaSlot:=false;  
 hFile:=CreateFile(JmenoSlotuV,
                   GENERIC_WRITE,
                   FILE_SHARE_READ,
                   nil,
                   OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL,
                   0);
 if (hFile=INVALID_HANDLE_VALUE) then exit;
 fResult := WriteFile(hFile,Slovo[0],StrLen(Slovo)+1,cbWritten,nil);
 if not(fResult) then exit;
 fResult := CloseHandle(hFile);
 if not(fResult) then exit;
 PosliNaSlot:=true;
end;

JmenoSlotuV je proměnná, kterou nastavíme podle toho, kam chceme zprávu směrovat. Samotná zpráva je zaslána v parametru Slovo.

Příjem dat je realizován opět jako čtení ze souboru. V první řadě se ale musí vytvořit mailslot pro příjem dat:

function VytvorMailSlot:boolean;
begin
 VytvorMailSlot:=false;
 hSlot1:=CreateMailslot(JmenoSlotuP,0,0,nil);
 if (hSlot1=INVALID_HANDLE_VALUE) then exit;
 VytvorMailSlot:=true;
end;

Proměnná hSlot1 je typu THandle a nese handle slotu pro příjem. Proměnná JmenoSlotuP je opět typu PChar a nese jméno slotu na lokálním počítači (tedy s tečkou). Například: vysílač v doméně má jméno slotu: \\*\mailslot\můjslot , přijímač bude data číst z \\.\mailslot\můjslot, nebo vysílač v doméně má jméno slotu: \\jménopočítače\mailslot\můjslot , přijímač na počítači se jménem "jménopočítače" bude data číst z \\.\mailslot\můjslot. Samotné čtení můžeme realizovat funkcí:

function CtiSlot(Opakovat:Boolean):String;
var cbMessage, cMessage, cbRead:DWord;
    fResult:Boolean;
    Buffer:array [0..65534] of char;
    Zprava:string;

procedure CtiZpravu;
begin
 Zprava:='';
 cbMessage:=0;
 cMessage:=0;
 cbRead:=0;
 fResult:=GetMailslotInfo(hSlot1,nil,cbMessage,@cMessage,nil);
 if not(fResult) or (cbMessage <= 0) then exit;
 Buffer[0]:=#0;
 fResult:=ReadFile(hSlot1,Buffer,cbMessage,cbRead,nil);
 if not(fResult) then exit;
 Zprava:=StrPas(Buffer);
end;

begin
 CtiSlot:='';
 if Opakovat then
 begin
  repeat
   Application.ProcessMessages;
   if KonecPGM then exit;
   CtiZpravu;
  until (Zprava<>'')
 end else CtiZpravu;
 CtiSlot:=Zprava;
end
;

Parametrem opakovat samozřejmě určíme, jestli má funkce na zprávu čekat (a vrátit ji ve formě řetězce), nebo jestli má v případě, že vstupní buffer je prázdný, vrátit prázdný řetězec. Po ukončení komunikace je dobré uzavřít slot například: CloseHandle (hSlot1); Vyčistit slot můžeme jeho uzavřením a znovuotevřením.

Jestliže chceme, aby programy komunikovaly vzájemně, musíme vytvořit dva komunikační kanály pro každý směr zvlášť. Navíc není dobré směrovat zprávy stále všem počítačům na síti. Zajímavé je řešení, kdy si programy při startu vymění svá jména na síti a další zprávy si směrují jen "mezi čtyřma očima", tedy mezi sebou. Není to ale tak jednoduché jak to vypadá, počítače jsou vždy různě rychlé a musí na sebe při výměně informací čekat. Já ve svých programech používám algoritmus, kdy program pošle zprávu, počká na příchozí zprávu a opět vyšle tu samou zprávu. Tento algoritmus vám umožní tvorbu programů, které budou komunikovat sami mezi sebou (jestli chcete tuto procedurku, napište si, já sám jsem jí odlaďoval 14 dní). Pokud jde například o čekání na tah soupeře (a tím i o čekání na data ze slotu), vkládám testování přítomnosti dat do obsluhy události OnIdle objektu Application.

Mailsloty jsou velmi jednoduchým způsobem realizace komunikace dvou programů na síti. Výhodou je i to, že můžeme program odlaďovat bez sítě s tím, že spustíme dva programy na jednom počítači (oba sloty mají pak označení \\.\mailsot\jedinečnéjméno). Jestliže si chcete vyzkoušet síťový program komunikující tímto způsobem, pak si stáhněte program Pyramida '97 a otestujte.

Směr