Vytvorenie databázy. Delphi: sieťové programovanie

  • 28.06.2019

V súčasnosti zostáva téma v oblasti informačných technológií venovaná vývoju a nasadeniu architektúry klient-server veľmi aktuálna. Je to spôsobené tým, že informačné systémy rôzneho rozsahu sa čoraz viac využívajú v rôznych oblastiach. Štruktúra každej databázy je navyše vytvorená podľa určitých parametrov a to tak, aby sa s ňou dalo pracovať v bežnom režime len s použitím špeciálnych aplikácií. Preto je implementácia architektúry "klient - server" veľmi dôležitou úlohou, ktorá vyvstáva pre oddelenia informačných technológií na rôznych miestach, ktorej úspešné riešenie umožní podniku optimálne a plynulo fungovať.

Server založený na zásuvke

Server soketového protokolu vám umožňuje súčasne spracovávať požiadavky od veľkého počtu používateľov. Zároveň môže správca kedykoľvek vykonať úpravy nastavení s cieľom zaviesť obmedzenie počtu súčasne obsluhovaných používateľov. Štandardne toto nastavenie nemá žiadne obmedzenia.

Po pripojení klienta k serveru sa otvorí samostatný kanál so soketom, cez ktorý sa vymieňajú dáta. Najoptimálnejšie a najbezpečnejšie je však nasadenie špeciálneho samostatného procesu pre každé nové pripojenie.

Schéma práce architektúry "Klient - server"

Pozrime sa podrobnejšie na schému implementácie architektúry, pričom postupne analyzujeme často používané definície:

1. Vlastnosti ServerType a Port. Aby sa používateľ mohol pripojiť k serveru, je dôležité zabezpečiť, aby bol port používaný serverom aj klientom rovnaký. Práve priradenie tohto parametra sa vykonáva vo vlastnosti Port. Typ pripojenia je určený parametrom ServerType.

2. Proces otvárania zásuvky. Ak chcete spustiť reláciu klient-server, je dôležité otvoriť soket a port. Používa sa vlastnosť Listen.

3. Ďalej prebieha výmena údajov s používateľom. Na konci práce je klient odpojený. Ak je to vhodné, server ukončí svoju prácu, preruší všetky vytvorené spojenia a zastaví proces čakania na nové spojenia.

Používanie TServerSocket v aplikáciách Delphi Client-Server

Udalosti OnClientWrite a OnClientRead sa používajú na odosielanie a prijímanie informácií od používateľa. Zároveň môžete komunikovať s používateľom prostredníctvom parametra, ako je ClientSocket. Pri práci sa často používajú nasledujúce metódy a vlastnosti:

Počet aktuálne pripojených používateľov;

Počet aktívnych procesov;

Počet voľných procesov;

Port, názov hostiteľa a lokálna IP adresa;

Odblokovanie a zablokovanie zásuvky.

Na záver venujme pozornosť často používanej špeciálnej vlastnosti – Dáta. Táto vlastnosť platí v nasledujúcej situácii. Spravidla sa server používa na obsluhu veľkého počtu používateľov, čo znamená, že je potrebné uchovávať informácie o každom klientovi a tieto informácie musia byť viazané na konkrétny soket. V takýchto situáciách je použitie manuálneho viazania veľmi nepohodlné, a preto je vlastnosť Data široko používaná. Je však dôležité mať na pamäti, že údaje sú ukazovateľ, a preto je dôležité skontrolovať, či sú dodržané všetky pravidlá pre prácu s ukazovateľmi (označenie typu, alokácia pamäte atď.)

Dokumentácia

K dnešnému dňu existuje veľmi málo literatúry o vývoji aplikácií klient-server Delphi súvisiacich s vývojom a používaním soketov. Pre podrobné preštudovanie tohto aspektu si preto môžete pozrieť dokumentáciu pre systémy Linux a Unix, pretože. dostatočne podrobne pokrýva technológiu nasadzovania aplikácií pomocou soketov, spravidla však v jazyku Perl alebo C++.

vyberte menu: Komponent - Inštalovať balíky ... - Pridať., potom musíte zadať súbor ... \ bin \ dclsockets70.bpl.

Prejdime priamo k vytvoreniu projektu klient-server, na začiatok na príklade sieťového chatu.

Sieťový chat pre dvoch používateľov

Spravidla sa vývoj akéhokoľvek programu začína definovaním úloh, ktoré musí vykonávať, a definovaním potrebných komponentov už v tejto fáze. Náš program je chat pre dvoch používateľov, z ktorých každý môže byť server aj klient, čo znamená, že do formulára hodíme komponenty ServerSocket a ClientSocket. Dôležitým parametrom pre obe je port. Len s rovnakou hodnotou nehnuteľnosti prístav, nadviaže sa spojenie medzi nimi. Vhoďte komponent do tvaru Upraviť na rýchlu zmenu portu, nazvime to PortEdit. Ak sa chcete pripojiť k serveru, musíte zadať IP servera alebo jeho názov, takže poďme ešte jeden Upraviť, nazvime to HostEdit. Potrebujeme aj ďalšie dve Upraviť"a ak chcete zadať prezývku a zadať text správy, zavolajte im." NikEdit a TextEdit, resp. Text prijatých a odoslaných správ sa zobrazí v poznámka, hodiť do tvaru a zavolať ChatMemo. Okamžite nastavíme zvislý posuvník: posuvníky = ssVertikálne a majetok iba na čítanie = Pravda. Pridať ovládacie klávesy tlačidlo: ServerBtn- vytvoriť/zatvoriť server, ClientBtn- pripojiť/odpojiť klienta od servera, SendBtn- posielať správy. Poďme sa zmeniť Popis tieto kľúče na " Vytvorte server", "pripojiť" a " Odoslať", respektíve. Posledným dotykom je pridanie nápisov štítok dať tvar správneho tvaru (toto je voliteľné).

Okamžite vás upozorním, nebudú sa vykonávať žiadne kontroly správnosti zadávania hodnôt do kódov, pretože to nie je hlavný cieľ. Šeky môžete ľahko vypisovať sami.

Definujme si, čo sa má stať pri vytváraní formulára. Poďme si popísať postup OnCreate:


začať
// navrhovaná hodnota portu
PortEdit.Text:="777";
// adresa pri kontrole programu na jednom PC ("pre seba")
HostEdit.Text:="127.0.0.1";
// stačí vyčistiť zvyšok polí
NikEdit.Clear;
TextEdit.Clear;
ChatMemo.Lines.Clear;
koniec;

Budeme predpokladať, že je zvolený režim servera. Prepnutie programu do serverového režimu sa vykoná stlačením " Vytvorte server" (ServerBtn). Aby ste nepoužívali ďalšie klávesy na deaktiváciu tohto režimu alebo podobných komponentov tlačítko na Rádiu, môžete použiť rovnakú vlastnosť Tag kľúče ServerBtn, zmenou jeho hodnôt a vykonaním určitých operácií, ak sa hodnota zhoduje so zadanou hodnotou. Takto vyzerá postup pri stlačení klávesu ServerBtn (po kliknutí):

procedure TForm1.ServerBtnClick(Sender: TObject);
začať
Ak ServerBtn.Tag=0, potom
Začať
// kľúč ClientBtn a polia HostEdit, PortEdit budú zablokované
ClientBtn.Enabled:=False;
HostEdit.Enabled:=False;
PortEdit.Enabled:=False;
// zapíše zadaný port do ServerSocket
ServerSocket.Port:=StrToInt(PortEdit.Text);
// spustenie servera
ServerSocket.Active:=True;
// pridanie správy s časom vytvorenia do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Server vytvorený");
// zmeniť značku
ServerBtn.Tag:=1;
// zmeniť označenie kľúča
ServerBtn.Caption:="Zavrieť server";
koniec
inak
Začať
// kľúč ClientBtn a polia HostEdit, PortEdit sú odomknuté
ClientBtn.Enabled:=True;
HostEdit.Enabled:=True;
PortEdit.Enabled:=True;
// zatvorte server
ServerSocket.Active:=False;

ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Server je zatvorený.");

ServerBtn.Tag:=0;

ServerBtn.Caption:="Vytvoriť server";
koniec;
koniec;

Poďme sa zaoberať udalosťami, ktoré by mali nastať v určitom stave ServerSocket"a. Napíšme procedúru, keď sa klient pripojí k serveru ( OnClientConnect):

procedure TForm1.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
začať
// pridanie správy s časom pripojenia klienta do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Klient je pripojený.");
koniec;

Napíšme postup, keď sa klient odpojí ( OnClientDisconnect):

procedure TForm1.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
začať
// pridanie správy do ChatMemo s časom odpojenia klienta
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Klient je odpojený.");
koniec;

Keď na server dorazí ďalšia správa od klienta, musíme ju okamžite zobraziť. Napíšme postup na čítanie správy od klienta ( OnClientRead):


Socket: TCustomWinSocket);
začať


koniec;

Najdôležitejšie je posielanie správ. Urobíme to stlačením tlačidla "Odoslať" ( SendBtn), ale musíte skontrolovať programový režim servera alebo klienta. Napíšeme jej postup ( po kliknutí):

procedure TForm1.SendBtnClick(Sender: TObject);
začať
// skontrolujte, v akom režime je program

// odoslať správu zo servera (je to číslo 0, pretože je to jediné)
ServerSocket.Socket.Connections.SendText("["+TimeToStr(Time)+"] "+NikEdit.Text+": "+TextEdit.Text)
inak
// odoslanie správy od klienta
ClientSocket.Socket.SendText("["+TimeToStr(Time)+"] "+NikEdit.Text+": "+TextEdit.Text);
// zobrazenie správy v ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] "+NikEdit.Text+": "+TextEdit.Text);
koniec;

Teraz sa poďme zaoberať klientskym režimom. Tu, naopak, keď stlačíte tlačidlo "Pripojiť" ( ClientBtn), je zablokovaný ServerBtn a aktivovaný ClientSocket. Tu je postup ClientBtn (OnClick):

procedure TForm1.ClientBtnClick(Sender: TObject);
začať
Ak ClientBtn.Tag=0, potom
Začať
// kľúč ServerBtn a polia HostEdit, PortEdit budú zablokované
ServerBtn.Enabled:=False;
HostEdit.Enabled:=False;
PortEdit.Enabled:=False;
// zapíše zadaný port do ClientSocket
ClientSocket.Port:=StrToInt(PortEdit.Text);
// zápis hostiteľa a adresy (jedna hodnota HostEdit v oboch)
ClientSocket.Host:=HostEdit.Text;
ClientSocket.Address:=HostEdit.Text;
// spustenie klienta
ClientSocket.Active:=True;
// zmeniť značku
ClientBtn.Tag:=1;
// zmeniť označenie kľúča
ClientBtn.Caption:="Odpojiť";
koniec
inak
Začať
// kľúč ServerBtn a polia HostEdit, PortEdit sú odomknuté
ServerBtn.Enabled:=True;
HostEdit.Enabled:=True;
PortEdit.Enabled:=True;
// zatvorte klienta
ClientSocket.Active:=False;
// zobrazenie správy v ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Relácia ukončená.");
// vráti značku na pôvodnú hodnotu
ClientBtn.Tag:=0;
// vráti pôvodné označenie kľúča
ClientBtn.Caption:="Pripojiť";
koniec;
koniec;

Zostáva napísať postupy pre Na Pripojenie, OnDisconnect, OnRead zákazník ClientSocket. Najprv si prečítajte správu zo servera ( OnRead):


Socket: TCustomWinSocket);
začať
// pridanie prichádzajúcej správy do ChatMemo
ChatMemo.Lines.Add(Socket.ReceiveText());
koniec;

procedure TForm1.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
začať
// pridanie správy o pripojení k serveru do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Pripája sa k serveru.");
koniec;

procedure TForm1.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
začať
// pridanie správy o strate komunikácie do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Server sa nenašiel.");
koniec;

Tu je minimum, ktoré je potrebné urobiť. Zostáva zaviesť niekoľko ďalších algoritmov na kontrolu správnosti zadávania niektorých hodnôt.
Vynára sa otázka: čo ak potrebujete preniesť dáta a nie reťazec, ale nejaký druh poľa? Na to existujú špeciálne príkazy. Skúsme napísať algoritmus na odoslanie poľa ako príkaz pre nejakú hru.

Odosielanie poľa údajov

Použime rovnaký chatovací formulár, stačí pridať niekoľko komponentov nižšie. Nech je úlohou spravovať objekt typu tvar, zmeniť typ geometrického útvaru, farbu, veľkosť. Umiestnite komponent na formulár skupinový box, a do toho tvar, ich mená budú rovnaké. Ak chcete zmeniť typ geometrického útvaru, použite zoznam combo box, nazvime to ShapeCBox. Nevyplníme to hneď, urobíme to OnCreate formulárov. Ďalej potrebujete to isté combo box pre výber farby a dve Upraviť"a na označenie veľkosti obrazca (v prípade obdĺžnika máme dve hodnoty, prvú použijeme pre kruh). Nazvime ich ColorCBox, Value1Edit, Value2Edit, resp. Posledný hod v zložke formulára tlačidlo, nazvime to SendBufBtn, Popis zmeniť na " Odoslať vyrovnávaciu pamäť".
Trochu o tom, ako prezentovať vstupné dáta ako dátovú vyrovnávaciu pamäť. Okamžite sa musíte v poradí rozhodnúť, ktorá hodnota nasleduje vo vyrovnávacej pamäti. Najprv nechajte typ tvaru, potom farbu a potom obe hodnoty veľkosti. Na tento účel by ste mali použiť pole dĺžky 4 a typ bajtov. Pridať do sekcie var pole:

Buf: pole bajtov;

S veľkosťou postavy je všetko jasné, ale pre typ a farbu potrebujete "pravdivosť". Predstavme si to takto:

kód parametra
obdĺžnik 0
kruh 1
-------------------
červená 0
zelená 1
modrá 2

Na ukážku to stačí. V prípade potreby je možné rozsah parametrov rozšíriť, zadať typ výplne, typ obrysu, odsadenie alebo použiť príklad na iné účely.
Zapisujeme plnenie zoznamov OnCreate formy:

procedure TForm1.FormCreate(Sender: TObject);
začať

// ...časť chatu...

// vypĺňanie zoznamov
ShapeCBox.Items.Add("obdĺžnik");
ShapeCBox.Items.Add("kruh");
ColorCBox.Items.Add("red");
ColorCBox.Items.Add("zelená");
ColorCBox.Items.Add("modrá");
koniec;

Keď stlačíte " Odoslať vyrovnávaciu pamäť"zozbierame údaje z polí a vytvoríme pole známej dĺžky a potom skontrolujeme režim server/klient a odošleme. Tu je postup SendBufBtn (OnClick):

procedure TForm1.SendBufBtnClick(Sender: TObject);
začať
// zbiera údaje na odoslanie
Buf:=ShapeCBox.ItemIndex;
Buf:=ColorCBox.ItemIndex;
Buf:=StrToInt(Value1Edit.Text);
Buf:=StrToInt(Value2Edit.Text);
// skontrolujte režim programu
Ak ServerSocket.Active=True, potom
// odoslanie vyrovnávacej pamäte zo servera (dĺžka je známa - 4)
ServerSocket.Socket.Connections.SendBuf(Buf;4)
inak
// odoslanie vyrovnávacej pamäte z klienta
ClientSocket.Socket.SendBuf(Buf,4);
// pridanie správy o prenose dát do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Údaje odoslané.");

Tvar.Výška:=Buf;
Shape.Width:=Buf;

Ak Buf>


Prípad Buf z
0: Shape.Brush.Color:=clRed;

2: Shape.Brush.Color:=clBlue;
koniec;
// zmena údajov v poliach
ShapeCBox.ItemIndex:=Buf;
ColorCBox.ItemIndex:=Buf;


koniec;

Trochu zmeňme postup čítania správy od klienta, vypnime možnosť prijímať správy a nakonfigurujme ju na príjem vyrovnávacej pamäte ( OnClientRead):

procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
len: Byte;
začať
// pridanie správy klienta do ChatMemo


len:=Socket.ReceiveLength;
Socket.ReceiveBuf(Buf,len);
// aplikujte zmeny na náš tvar
Tvar.Výška:=Buf;
Shape.Width:=Buf;
Ak Buf>0, potom Shape.Shape:=stCircle(circle)
else Shape.Shape:=stRectangle; (obdĺžnik)
// výber farby podľa pravdivostnej tabuľky
Prípad Buf z
0: Shape.Brush.Color:=clRed;
1: Shape.Brush.Color:=clGreen;
2: Shape.Brush.Color:=clBlue;
koniec;
// zmena údajov v poliach
ShapeCBox.ItemIndex:=Buf;
ColorCBox.ItemIndex:=Buf;
Value1Edit.Text:=IntToStr(Buf);
Value2Edit.Text:=IntToStr(Buf);


koniec;

Zostáva podobným spôsobom zmeniť procedúru pre klienta na čítanie správy zo servera ( OnRead):

procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
len: Byte;
začať
// pridanie správy zo servera do ChatMemo
// ChatMemo.Lines.Add(Socket.ReceiveText());
// akceptovanie vyrovnávacej pamäte neznámej veľkosti
len:=Socket.ReceiveLength;
Socket.ReceiveBuf(Buf,len);
// aplikujte zmeny na náš tvar
Tvar.Výška:=Buf;
Shape.Width:=Buf;
Ak Buf>0, potom Shape.Shape:=stCircle(circle)
else Shape.Shape:=stRectangle; (obdĺžnik)
// výber farby podľa pravdivostnej tabuľky
Prípad Buf z
0: Shape.Brush.Color:=clRed;
1: Shape.Brush.Color:=clGreen;
2: Shape.Brush.Color:=clBlue;
koniec;
// zmena údajov v poliach
ShapeCBox.ItemIndex:=Buf;
ColorCBox.ItemIndex:=Buf;
Value1Edit.Text:=IntToStr(Buf);
Value2Edit.Text:=IntToStr(Buf);
// pridanie správy o príchode údajov do ChatMemo
ChatMemo.Lines.Add("["+TimeToStr(Time)+"] Údaje prišli.");
koniec;

To je všetko. Upozorňujeme, že ak nezakážete prijímanie správ ( Socket.ReceiveText()) a pokúsiť sa prijať správu aj vyrovnávaciu pamäť súčasne, bude to mať za následok stratu údajov jednej z funkcií. Tieto problémy môžete vyriešiť prekladom správy do formátu vyrovnávacej pamäte, ako je tento:

Pre i:=1 to Length(TextEdit.Text) urobte
Buf:=Copy(TextEdit.Text,i,1);

Je zrejmé, že pole sa zväčší o jednu bunku a zmení svoj typ na znak alebo reťazec. Buf v tomto prípade bude slúžiť ako označenie, čo je prichádzajúca vyrovnávacia pamäť: správa alebo dáta. V postupoch prijímania správ musíte vytvoriť podmienku, ako je táto:

len:=Socket.ReceiveLength;
Socket.ReceiveBuf(Buf,len);
Ak Buf="t" tak
Začať
... vykonajte operáciu spojenia reťazcov (cez slučku)
koniec;
Ak Buf="c" tak
Začať
... vykonajte operáciu na zmenu parametrov tvaru
koniec;

Úvod

Tento článok je o vytváraní aplikácií klient/server založených na soketoch v Borland Delphi („sockety“ - hniezda). Na rozdiel od predchádzajúceho článku na tému soketov si tu rozoberieme tvorbu serverových aplikácií.

Hneď je potrebné poznamenať, že pre koexistenciu samostatných klientskych a serverových aplikácií nie je potrebné mať niekoľko počítačov. Stačí mať len jeden, na ktorom môžete súčasne spustiť server aj klienta. V tomto prípade musíte použiť názov hostiteľa ako názov počítača, ku ktorému sa chcete pripojiť. localhost alebo IP adresa - 127.0.0.1 .

Začnime teda teóriou. Ak ste oddaným odborníkom (a nevidíte žiadne algoritmy očami), mali by ste túto časť preskočiť.

Algoritmus soketového servera

Čo robí soketový server?... Ako to funguje?.. Server založený na soketovom protokole vám umožňuje obsluhovať veľa klientov naraz. Okrem toho môžete sami určiť limit na ich počet (alebo tento limit úplne odstrániť, ako sa to robí štandardne). Pre každého pripojeného klienta server otvorí samostatný soket, cez ktorý si môžete vymieňať dáta s klientom. Skvelým riešením je tiež vytvorenie samostatného procesu (vlákna) pre každé pripojenie.

Poďme analyzovať schému podrobnejšie:

  • Definovanie vlastností v Port a ServerType - aby sa klienti mohli normálne pripojiť k serveru, port používaný serverom sa musí presne zhodovať s portom používaným klientom (a naopak). Vlastnosť ServerType určuje typ pripojenia (podrobnosti nájdete nižšie);
  • otvor zásuvky - Otvorenie zásuvky a určeného portu. Tu sa vykoná automatické spustenie čakania na pripojenie klientov ( Počúvaj);
  • Pripojenie klienta a výmena údajov s ním - tu sa klient pripája a vymieňajú sa s ním dáta. Viac o tejto fáze sa dozviete neskôr v tomto článku a v článku o zásuvkách (strana klienta);
  • Zakázanie klienta - Tu sa klient odpojí a jeho soketové spojenie so serverom sa uzavrie;
  • Zatvorenie servera a soketu - Na príkaz administrátora server ukončí svoju prácu, zatvorí všetky otvorené soketové kanály a prestane čakať na pripojenia klientov.

Treba si uvedomiť, že body 3-4 sa mnohokrát opakujú, t.j. tieto položky sa vykonajú pre každé nové pripojenie klienta.

Poznámka : V Delphi je momentálne veľmi málo dokumentácie k socketom, takže ak si chcete túto tému naštudovať čo najhlbšie, potom vám odporúčam preštudovať si literatúru a elektronickú dokumentáciu o systémoch Unix/Linux – tam veľmi Teória práce so zásuvkami je dobre popísaná. Okrem toho existuje veľa príkladov soketových aplikácií pre tieto OS (väčšinou však v C/C++ a Perl).

Stručný popis komponentu TServerSocket

Tu sa zoznámime hlavné vlastnosti, metódy a udalosti komponentu TServerSocket.

Vlastnosti Metódy Vývoj
Zásuvka - trieda TServerWinSocket, prostredníctvom ktorej máte prístup k otvoreným soketovým kanálom. Ďalej budeme túto vlastnosť uvažovať podrobnejšie, pretože. je v skutočnosti jedným z hlavných. Typ: TServerWinSocket ;
Typ servera - typ servera. Môže nadobudnúť jednu z dvoch hodnôt: stNonBlocking- synchrónna práca s klientskymi zásuvkami. S týmto typom servera môžete pracovať s klientmi prostredníctvom udalostí OnClientRead a OnClientWrite. stThreadBlocking- asynchrónny typ. Pre každý klientsky soketový kanál sa vytvorí samostatný proces (vlákno). Typ: TServerType ;
ThreadCacheSize - počet klientskych procesov (vlákno), ktoré bude server ukladať do vyrovnávacej pamäte. Tu musíte vybrať priemernú hodnotu v závislosti od zaťaženia vášho servera. Ukladanie do vyrovnávacej pamäte nastáva preto, aby sa zakaždým nevytvoril samostatný proces a nezabil sa uzavretý soket, ale aby sa nechali na ďalšie použitie. Typ: Celé číslo ;
Aktívne - indikátor, či je server momentálne aktívny alebo nie. To je v skutočnosti hodnota Pravda označuje, že server je spustený a pripravený prijímať klientov a Nepravdivé- server je vypnutý. Ak chcete spustiť server, stačí nastaviť túto vlastnosť na Pravda. Typ: Boolean ;
prístav - číslo portu pre nadviazanie spojenia s klientmi. Port na serveri a klientoch musí byť rovnaký. Odporúčané sú hodnoty od 1025 do 65535 od 1 do 1024 - môže byť obsadené systémom. Typ: Celé číslo ;
servis - reťazec definujúci službu ( ftp, http, pop, atď.), ktorého port sa použije. Toto je druh referenčnej knihy na porovnávanie čísel portov s rôznymi štandardnými protokolmi. Typ: reťazec ;
OTVORENÉ - Spustí server. Tento príkaz je v podstate identický s priradením hodnoty Pravda nehnuteľnosť Aktívne;
Zavrieť - Zastaví server. Tento príkaz je v podstate identický s priradením hodnoty Nepravdivé nehnuteľnosť Aktívne.
OnClientConnect - vyskytuje sa, keď klient nadviazal pripojenie soketu a čaká na odpoveď zo servera ( OnAccept);
OnClientDisconnect - nastane, keď sa klient odpojí od soketového kanála;
OnClientError - nastáva, keď aktuálna operácia zlyhala, t.j. Došlo k chybe;
OnClientRead - nastane, keď klient odoslal nejaké údaje berverovi. K týmto údajom je možné pristupovať prostredníctvom odovzdaného parametra. Zásuvka: TCustomWinSocket;
OnClientWrite - nastane, keď server môže odoslať dáta klientovi na soket;
OnGetSocket - v handleri tejto udalosti môžete upraviť parameter ClientSocket;
OnGetThread - v handleri tejto udalosti môžete definovať jedinečný proces (vlákno) pre každý individuálny klientsky kanál nastavením parametra SocketThread požadovaná podúloha TServerClientThread;
OnThreadStart , OnThreadEnd - nastane, keď sa spustí alebo zastaví čiastková úloha (proces, vlákno);
OnAccept - nastane, keď server prijme klienta alebo odmietne spojenie;
OnListen - Vyskytuje sa, keď server prejde do režimu čakania na pripojenie klientov.

TServerSocket.Socket(TServerWinSocket)

Ako teda môže server odosielať údaje klientovi? Ako je to s prijímaním údajov? V podstate ak pracujete cez udalosti OnClientRead a OnClientWrite, potom môžete komunikovať s klientom prostredníctvom parametra ClientSocket (TCustomWinSocket). O práci s touto triedou si môžete prečítať v článku o klientskych soketoch. posielanie/odosielanie dát cez túto triedu je podobné - metódy (Send/Receive)(Text,Buffer,Stream). Tiež pri práci s TServerSocket.Socket. Avšak, keďže Keďže uvažujeme o serveri, je potrebné zdôrazniť niektoré užitočné vlastnosti a metódy:

  • ActiveConnections (Celé číslo) - počet pripojených klientov;
  • ActiveThreads (Celé číslo) je počet spustených procesov; Spojenia (pole) je pole pozostávajúce z jednotlivých tried TClientWinSocket pre každého pripojeného klienta. Napríklad tento príkaz:
    ServerSocket1.Socket.Connections.SendText("Ahoj!");
    odošle správu „Ahoj!“ prvému pripojenému klientovi. Príkazy na prácu s prvkami tohto poľa sú tiež (Send/Receive)(Text,Buffer, Stream);
  • IdleThreads (Celé číslo) je počet voľných procesov. Takéto procesy ukladá server do vyrovnávacej pamäte (pozri ThreadCacheSize);
  • miestna adresa, localhost, miestny prístav- v tomto poradí - lokálna IP adresa, názov hostiteľa, port;
  • vzdialená adresa, vzdialený hostiteľ, vzdialený port- v tomto poradí - vzdialená IP adresa, názov hostiteľa, port;
  • Metódy zámok a odomknúť- blokovanie a odblokovanie zásuvky.

Prax a príklady

Teraz sa pozrime na vyššie uvedené na konkrétnom príklade. Hotové zdroje si môžete stiahnuť kliknutím na .

Pozrime sa teda na veľmi dobrý príklad práce s TServerSocket (tento príklad je najnázornejšia pomôcka na učenie sa tohto komponentu). Nižšie uvedené zdroje demonštrujú protokolovanie všetkých dôležitých udalostí servera a navyše možnosť prijímať a odosielať textové správy:

Príklad 1 Prihlásenie a štúdium práce servera, odosielanie / prijímanie správ cez zásuvky.

(... Tu je hlavička súboru a definícia formulára TForm1 a jeho inštancie Form1) (Pozri celý zdroj) procedure TForm1.Button1Click(Sender: TObject); začať (definujeme port a spustíme server) ServerSocket1.Port:= 1025; (Metóda Insert vloží reťazec do poľa na zadanú pozíciu) Memo2.Lines.Insert(0,"Server sa spúšťa"); ServerSocket1.Open; koniec; procedure TForm1.Button2Click(Sender: TObject); začať (Zastavte server) ServerSocket1.Active:= False; Memo2.Lines.Insert(0,"Server zastavený"); koniec; procedure TForm1.ServerSocket1Listen(Sender: TObject; Socket: TCustomWinSocket); začať (Tu server "počúva" na sockete pre klientov) Memo2.Lines.Insert(0,"Počúvanie na porte "+IntToStr(ServerSocket1.Port)); koniec; procedure TForm1.ServerSocket1Accept(Sender: TObject; Socket: TCustomWinSocket); začať (Tu server akceptuje klienta) Memo2.Lines.Insert(0,"Pripojenie klienta akceptované"); koniec; procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); začať (Tu sa klient pripojí) Memo2.Lines.Insert(0,"Klient pripojený"); koniec; procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); začať (Tu sa klient odpojí) Memo2.Lines.Insert(0,"Klient odpojený"); koniec; procedure TForm1.ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); začať (Vyskytla sa chyba - vytlačte jej kód) Memo2.Lines.Insert(0,"Chyba klienta. Kód = "+IntToStr(ErrorCode)); koniec; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); začať (Správa bola prijatá od klienta - zobrazujeme ju v Memo1) Memo2.Lines.Insert(0,"Správa prijatá od klienta"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); koniec; procedure TForm1.ServerSocket1ClientWrite(Sender: TObject; Socket: TCustomWinSocket); začať (Teraz môžete posielať dáta do zásuvky) Memo2.Lines.Insert(0,"Teraz môže zapisovať do zásuvky"); koniec; procedure TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer; var ClientSocket: TServerClientWinSocket); begin Memo2.Lines.Insert(0,"Získať zásuvku"); koniec; procedure TForm1.ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin Memo2.Lines.Insert(0,"Získať vlákno"); koniec; procedure TForm1.ServerSocket1ThreadEnd(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Koniec vlákna"); koniec; procedure TForm1.ServerSocket1ThreadStart(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Začiatok vlákna"); koniec; procedure TForm1.Button3Click(Sender: TObject); var i: celé číslo; začať (Pošlite VŠETKÝM klientom správu z Edit1) for i:= 0 to ServerSocket1.Socket.ActiveConnections-1 začnite ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); koniec; Memo1.Lines.Insert(0,"< "+Edit1.Text); end;

Techniky pre prácu s TServerSocket (a len soketmi)

Ukladanie jedinečných údajov pre každého klienta.

Iste, ak váš server bude obsluhovať veľa klientov, potom budete musieť uložiť nejaké informácie pre každého klienta (meno atď.) a naviazaním týchto informácií na socket tohto klienta. V niektorých prípadoch nie je toto všetko robiť manuálne (pripojenie na rukoväť soketu, polia klientov atď.). Preto existuje špeciálna vlastnosť pre každú zásuvku - Údaje. V skutočnosti je Data len ukazovateľ. Preto pri zápise klientskych dát do tejto vlastnosti buďte opatrní a dodržujte pravidlá pre prácu s pointermi (alokácia pamäte, typová inferencia a pod.)!

Posielanie súborov cez soket.

Tu sa pozrieme na posielanie súborov cez soket (ako to požaduje JINX) :-). Ako teda odošlete súbor cez soket? Veľmi jednoduché! Tento súbor stačí otvoriť ako súborový stream (TFileStream) a odoslať ho cez socket (SendStream)! Pozrime sa na to na príklade:

Treba poznamenať, že metóda sendstream používa nielen server, ale aj klient ( ClientSocket1.Socket.SendStream(srcfile))

Prečo je možné počas prenosu spojiť niekoľko blokov do jedného?

To žiada aj JINX :-). Za to mu patrí veľká vďaka! Po prvé, treba poznamenať, že údaje odoslané cez zásuvku môžu byť nielen spojené do jedného bloku, ale aj rozdelené do niekoľkých blokov. Faktom je, že soket je normálny stream, ale na rozdiel od povedzme súborového streamu (TFileStream) prenáša dáta pomalšie (rozumej - sieť, obmedzená prevádzka atď.). Preto dva príkazy:
ServerSocket1.Socket.Connections.SendText("Dobrý deň, ");
ServerSocket1.Socket.Connections.SendText("svet!");
sú úplne totožné s jedným príkazom:
ServerSocket1.Socket.Connections.SendText("Ahoj, svet!");

A to je dôvod, prečo, ak pošlete súbor, povedzme, 100 Kb, cez socket, potom osoba, ktorej ste poslali tento blok, dostane niekoľko blokov s veľkosťami, ktoré závisia od prevádzky a zaťaženia linky. Navyše, rozmery nemusia byť rovnaké. Z toho vyplýva, že ak chcete prijať súbor alebo akékoľvek iné veľké údaje, mali by ste prijať bloky údajov a potom ich spojiť do jedného celku (a uložiť napríklad do súboru). Výborným riešením tohto problému je rovnaký súborový stream - TFileStream (alebo stream v pamäti - TMemoryStream). Dátové častice zo zásuvky môžete prijímať prostredníctvom udalosti OnRead (OnClientRead) pomocou univerzálnej metódy ReceiveBuf. Pomocou metódy môžete určiť veľkosť výsledného bloku ReceiveLength. Môžete tiež použiť stream soketov (pozri článok TClientSocket). A tu je malý príklad (približný):

Ako monitorovať zásuvku

Tento problém je zložitý a vyžaduje si dlhé zváženie. Zatiaľ len poznamenám, že zásuvku vytvorenú vaším programom môžete sledovať vždy :-). Zásuvky (ako väčšina objektov vo Windows) majú svoj vlastný handle (handle), napísaný vo vlastnosti Handle. Takže, keď sa naučíte tento deskriptor, môžete voľne ovládať akúkoľvek zásuvku (dokonca aj tú, ktorú vytvoril program niekoho iného)! S najväčšou pravdepodobnosťou však budete musieť použiť funkcie WinAPI Sockets na sledovanie cudzej zásuvky.

Epilóg

Tento článok ukazuje základné triky pre prácu s komponentom TServerSocket v Delphi a niekoľko všeobecných trikov na komunikáciu cez sockety. Ak máte nejaké otázky - pošlite mi ich na e-mail: [chránený e-mailom], a ešte lepšie - napíšte do fóra tejto stránky (Delphi. Všeobecné otázky), aby ostatní používatelia videli vašu otázku a pokúsili sa na ňu odpovedať!

Karikh Nikolay ( Nitro). Moskovský región, Žukovskij

Keďže je aplikácia najjednoduchšia, rozhodol som sa použiť databázu MS Jet 4.0 (inými slovami, databázu MS Access). Toto rozhodnutie je spôsobené tým, že Jet (nezamieňajte si ho s MS Access) je bezplatný produkt a je dodávaný s MS Windows (to znamená, že pre fungovanie nášho programu nie je potrebné inštalovať samotný Access na klientsky počítač ). Áno, a editor databázy je veľmi dobrý a jadro podporuje množstvo typov polí na uspokojenie tých najzvrátenejších túžob pri ukladaní údajov.

Vytvorme si teda novú databázu, nazvime ju Test a uložíme do priečinka C:\ClientServer\Server\Data (z pochopiteľných dôvodov proces vytvárania novej databázy v Accesse vynechávam a uvediem len štruktúru tabuliek zahrnuté v našej databáze).

1. Prvá tabuľka, nazvime ju Prvá (no, nie som spisovateľ!)

2. Druhý stôl, ale nazvime to ošemetne – Druhý

No akože s bázou a hotovo.

2. Program
2.1. Serverová aplikácia.

Vytvorme novú aplikáciu a uložíme ju pod názvom Server do priečinka C:\ClientServer\Server. Pridajme do aplikácie Remote Data Module zo záložky Multitier úložiska (obr. 1).

Pri pridávaní RDM sa sprievodca pridaním opýta na parametre tohto modulu - tam zadáme názov nášho servera "Test".

Všetko ostatné necháme nezmenené. Po kliknutí na tlačidlo „OK“ sa v projekte objaví formulár podobný bežnému dátovému modulu s názvom Test. Uložte si ho pod menom RDMFrm.pas.

Rozložíme naň komponenty ADOConnection (jeden kus), ADOTable a DataSetProvider (po dva kusy). Komponenty ADOTable a DataSetProvider nazvime adotFirst, adotSecond, dspFirst a dspSecond. Dvojitým kliknutím na komponent ADOConnection sa zobrazí sprievodca Connection String. Vyberte položku "Použiť reťazec pripojenia" a stlačte tlačidlo Vytvoriť. V zobrazenom okne "Data Link Properties" vyberte položku "Microsoft Jet 4.0 OLE DB Provider" a kliknite na tlačidlo "Next". Na karte "Pripojenie" zadajte cestu k databáze, stlačte tlačidlo "Skontrolovať pripojenie" a dostanete správu, že kontrola pripojenia bola dokončená. Potom zatvorte sprievodcu kliknutím na tlačidlo OK. Komponent ADOConnection má aj vlastnosť LoginPrompt, ktorú nastavíme na False a Connected - True. Pre komponenty ADOTable nastavte vlastnosť Connection na ADOConnection výberom z rozbaľovacieho zoznamu. Nastavte vlastnosť TableName na First a Second. Vlastnosť CursorType je ctDynamic, vlastnosť TableDirect je True. Zavolajte FieldsEditor a pridajte tam všetky polia.

Pre komponenty DataSetProvider:

Tu je možné považovať proces vytvárania primitívneho servera MIDAS za dokončený. Ak chcete zaregistrovať server v subsystéme DCOM, musíte spustiť aplikáciu s parametrom /regserver - Server.exe /regserver.
A posledným dotykom je aplikácia Borland's SocketServer, ktorá sa nachádza v priečinku Delphi?/Bin/scktsvr.exe. Aby klient videl server, musíte spustiť scktsvr.exe (ak máte nainštalovaný Win NT / w2k / XP, môžete si túto aplikáciu zaregistrovať ako službu, preto ju musíte spustiť pomocou scktsvr.exe / parameter inštalácie)

2.2. Aplikačný klient

Vytvorme si novú aplikáciu a uložíme ju do priečinka C:\ClientServer\Client pod názvom Klient. Na hlavný formulár umiestnime dva komponenty ClientDataSet (nazvime ich cdsFirst, cdsSecond), DataSource (nazvime ich dsFirst, dsSecond), DBGrid (nazvime ich dbgFirst, dbgSecond) a jeden komponent SocetConnection.

SocketConnection

Ak ste urobili všetko správne, potom keď nastavíte vlastnosť Connected na True, serverová aplikácia by sa mala spustiť.

ClientDataSet

Spustíme Editor polí (dvojklik na komponent) a pridáme tam všetky polia. Pre komponenty ClientDataSet napísať handler sdsAfterPost

A nahraďte ho spracovaním udalostí postpost obe sady ClientDataSets.

Zdroj dát

Nehnuteľnosť Význam
súbor údajovcdsFirst a cdsSecond

dbgrid

Nehnuteľnosť Význam
Zdroj dátdsFirst a dsSecond

Spustite Editor stĺpcov (dvakrát kliknite na komponent) a pridajte tam všetky polia.
Umiestnime tlačidlo na formulár v blízkosti Grids a napíšeme ho do obsluhy onClick.

Vytvorme si teda novú databázu, nazvime ju Test a uložíme do priečinka C:\ClientServer\Server\Data (z pochopiteľných dôvodov proces vytvárania novej databázy v Accesse vynechávam a uvediem len štruktúru tabuliek zahrnuté v našej databáze).

1. Prvý stôl, nazvime ho Prvý

2. Druhý stôl, ale nazvime to ošemetne – Druhý

No akože s bázou a hotovo.

Program

2.1. Serverová aplikácia.

Vytvorme novú aplikáciu a uložíme ju pod názvom Server do priečinka C:\ClientServer\Server. Pridajme do aplikácie Remote Data Module zo záložky Multitier úložiska (obr. 1).

Ryža. 1 úložisko s vyhradeným modulom vzdialených údajov.

Pri pridávaní RDM sa sprievodca pridaním opýta na parametre tohto modulu - tam zadáme názov nášho servera "Test".


Všetko ostatné necháme nezmenené. Po kliknutí na tlačidlo „OK“ sa v projekte objaví formulár podobný bežnému dátovému modulu s názvom Test. Uložte si ho pod menom RDMFrm.pas.

Rozložíme naň komponenty ADOConnection (jeden kus), ADOTable a DataSetProvider (po dva kusy). Komponenty ADOTable a DataSetProvider nazvime adotFirst, adotSecond, dspFirst a dspSecond. Dvojitým kliknutím na komponent ADOConnection sa zobrazí sprievodca Connection String. Vyberte položku "Použiť reťazec pripojenia" a stlačte tlačidlo Vytvoriť. V zobrazenom okne "Data Link Properties" vyberte položku "Microsoft Jet 4.0 OLE DB Provider" a kliknite na tlačidlo "Next". Na karte "Pripojenie" zadajte cestu k databáze, stlačte tlačidlo "Skontrolovať pripojenie" a dostanete správu, že kontrola pripojenia bola dokončená. Potom zatvorte sprievodcu kliknutím na tlačidlo OK. Komponent ADOConnection má aj vlastnosť LoginPrompt, ktorú nastavíme na False a Connected - True. Pre komponenty ADOTable nastavte vlastnosť Connection na ADOConnection výberom z rozbaľovacieho zoznamu. Nastavte vlastnosť TableName na First a Second. Vlastnosť CursorType je ctDynamic, vlastnosť TableDirect je True. Zavolajte FieldsEditor a pridajte tam všetky polia.

Pre komponenty DataSetProvider:

Tu je možné považovať proces vytvárania primitívneho servera MIDAS za dokončený. Ak chcete zaregistrovať server v subsystéme DCOM, musíte spustiť aplikáciu s parametrom /regserver - Server.exe /regserver.
A posledným dotykom je aplikácia Borland's SocketServer, ktorá sa nachádza v priečinku Delphi?/Bin/scktsvr.exe. Aby klient videl server, musíte spustiť scktsvr.exe (ak máte nainštalovaný Win NT / w2k / XP, môžete si túto aplikáciu zaregistrovať ako službu, preto ju musíte spustiť pomocou scktsvr.exe / parameter inštalácie)

2.2. Aplikačný klient

Vytvorme si novú aplikáciu a uložíme ju do priečinka C:\ClientServer\Client pod názvom Klient. Na hlavný formulár umiestnime dva komponenty ClientDataSet (nazvime ich cdsFirst, cdsSecond), DataSource (nazvime ich dsFirst, dsSecond), DBGrid (nazvime ich dbgFirst, dbgSecond) a jeden komponent SocetConnection.

SocketConnection

Ak ste urobili všetko správne, potom keď nastavíte vlastnosť Connected na True, serverová aplikácia by sa mala spustiť.

ClientDataSet

Spustíme Editor polí (dvojklik na komponent) a pridáme tam všetky polia. Pre komponenty ClientDataSet napísať handler sdsAfterPost

Procedure TMainForm.cdsAfterPost(Množina údajov: množina TData);
začať
s (DataSet ako TClientDataSet) začať
ak štát vtedy
skúste
ApplyUpdates(0);
Obnoviť;
okrem
raise EDatabaseError.Create("Vyskytla sa chyba");
koniec;
koniec;
koniec;

A nahraďte ho spracovaním udalostí postpost obe sady ClientDataSets.

Zdroj dát

Nehnuteľnosť Význam
súbor údajov cdsFirst a cdsSecond

dbgrid

Nehnuteľnosť Význam
Zdroj dát dsFirst a dsSecond

Spustite Editor stĺpcov (dvakrát kliknite na komponent) a pridajte tam všetky polia.
Umiestnime tlačidlo na formulár v blízkosti Grids a napíšme do obsluhy onClick:

  • pre dbgFirst - cdsFirst.Post
  • dbgSecond - cdsSecond.Post

Všetky. Zatvorte Delphi (kvôli čistote experimentu). A spustíme klientsku aplikáciu. Ak ste urobili všetko správne, mali by ste vidieť niečo také


Ak článok získa spätnú väzbu a zaujme čitateľov, pokračovanie na seba nenechá dlho čakať.