Delphi aljzat csatlakozás ellenőrzése. Delphi. Socket programozás Delphiben. Összetett adatok küldése és fogadása

Aljzatok (az aljzatból (angol) - csatlakozó, aljzat) vannak szoftver interfész, amely biztosítja a folyamatok közötti információcserét.

A hálózaton belüli socket-kommunikáció egyik fő előnye a rugalmassága. A socketekkel való munkavégzés fő elve egy bájtsorozat küldése egy másik számítógépre, ez lehet egyszerű szöveges üzenet vagy fájl.

Fontos különbséget tenni két típusú aljzat között: ügyfélaljzatok , És szerver aljzatok .

A Delphi "kliens" típusú aljzataival való együttműködéshez van egy összetevő TClientSocket, akkor a komponens segítségével dolgozhat "szerver" socketekkel TServerSocket.

Alkatrészek telepítése

A TServerSocket és a TClientSocket összetevők gyakran nem szerepelnek a szabványos Delphi telepítőcsomagban, de külön is telepíthetők.

Lépjen az "Internet" összetevők fülre, és ellenőrizze, hogy ott vannak-e a TServerSocket és a TClientSocket összetevők, ha nem, telepítse őket. Lépjen a "Component/Install Packages" menübe, majd kattintson a "Hozzáadás" gombra. A megnyíló párbeszédpanelen meg kell találnia a "dclsocketsXX.bpl" fájlt (a bin mappában található, amely a Delphi mappájában található), ahol az XX a Delphi numerikus verziószáma. Keresse meg a fájlt, kattintson a Megnyitás gombra, majd kattintson az OK gombra a Csomagok telepítése ablakban. Most két összetevő jelent meg az "Internet" lapon - a TServerSocket és a TClientSocket.

Munkavégzés kliens socketekkel (tClientSocket)

1) A port és a gazdagép tulajdonságainak meghatározása. A sikeres kapcsolathoz tulajdonságok kikötőÉs Házigazda a TClientSocket komponenshez hozzá kell rendelni néhány értéket. A Port tulajdonságban meg kell adnia a csatlakozás portszámát (1 - 65535, de jobb az 1001 - 65535 tartományból venni, mert az 1000-ig terjedő számokat rendszerszolgáltatások foglalhatják el).

Házigazda- annak a számítógépnek a gazdagépneve vagy IP-címe, amelyhez csatlakozni kíván. Például rus.delphi.com vagy 192.128.0.0.

2) Egy aljzat kinyitása. A socketet az egyik számítógépről a másikra továbbított karakterek sorának tekintjük. Socketet a metódus meghívásával nyithat nyisd ki(TClientSocket komponens) vagy érték hozzárendelésével Igaz ingatlan Aktív. Ide célszerű egy kivételkezelőt tenni sikertelen kapcsolat esetén.

3) Adatok küldése/fogadása.

4) Az aljzat bezárása. Az adatcsere befejeztével le kell zárni a socketet a metódus hívásával Bezárásösszetevő TClientSocket vagy érték hozzárendelésével Hamis ingatlan Aktív.

A TClientSocket összetevő alapvető tulajdonságai

Jelzés, hogy az aljzat nyitva van vagy zárva. Megnyitva – Igaz érték, zárva – Hamis érték. Felvételre elérhető.

Hostnév a csatlakozáshoz

Annak a számítógépnek az IP-címe, amelyhez csatlakozni kíván. A Hosttal ellentétben itt csak az IP adható meg. A különbség az, hogy ha a Host szó szerinti számítógépnevet tartalmaz, akkor az IP-t a DNS kéri

A csatlakoztatandó számítógép portszáma (1-65535)

ClientType

Az adatátvitel típusát tartalmazza:

ctBlocking- szinkron átvitel ( OnReadÉs OnWrite nem működik). A szinkron kapcsolat típusa alkalmas streaming adatcserére;

ctNonBlocking- aszinkron átvitel (az adatok küldése / fogadása történhet események segítségével OnReadÉs OnWrite)

A TClientSocket komponens alapvető módszerei

Megnyit egy socketet (az Aktív tulajdonság igaz értékre állításával)

Bezárja a socketet (az Active tulajdonságot False értékre állítva)

A TClientSocket komponens fő eseményei

On Connect

A kapcsolat létrejöttekor fordul elő. A kezelőben már megkezdheti az engedélyezést vagy az adatok küldését/fogadását

On Connecting

Csatlakozáskor is előfordul. Abban különbözik az OnConnecttől, hogy a kapcsolat még nem jött létre. Leggyakrabban például az állapot frissítésére használják

OnDisconnect

Az esemény akkor következik be, amikor a socketet bezárja a program, a távoli számítógép vagy hiba miatt

Az esemény hiba miatt van előidézve. A socket megnyitása közben ez az esemény nem segít elkapni a hibát. A Windows hibaüzenetének elkerülése érdekében a legjobb, ha gondoskodik a belső kivételkezelésről úgy, hogy a nyitott utasításokat egy " próbáld meg..kivéve »

OnLookup

Az esemény akkor következik be, amikor megpróbál IP-címet kérni a DNS-től

Az esemény akkor következik be, amikor egy távoli számítógép küld Önnek néhány adatot. Az OnRead hívásakor lehetőség van a fogadott adatok feldolgozására

Az esemény akkor lép fel, amikor a program engedélyezi, hogy adatokat írjon a socketbe

Ez a cikk az alapvető tulajdonságokkal és funkciókkal foglalkozik Delphi alkatrészek: TClientSocket és TServerSocket – a TCP\IP protokollt használó hálózattal való együttműködésre szolgál.

Figyelem! Ha a Delphi 6.0-nál magasabb verzióját használja, akkor először telepítenie kell a Sockets Components szoftvert, a Delphi összes verziójában ez a következőképpen történik:

  • Lépjen a Csomagok telepítése… párbeszédpanelre: (Főmenü) Komponens -> Csomagok telepítése;
  • Kattintson a Hozzáadás gombra, ami után megkeressük Delphi-je Bin mappáját (pl.: C:\Program Files\Borland\Delphi 7\bin vagy C:\Program Files\Embarcadero\RAD Studio\7.0\Bin);
  • A megtalált Bin mappában már keresünk egy fájlt dclsockets [számok itt].bpl, kattintson az OK gombra;
  • Örülünk, mert most két csodálatos komponensünk van, a TServerSocket és a TClientSocket az Internet fül komponens panel lapján.

Bármilyen hálózati alkalmazás fejlesztésekor a fejlesztés általában mindig a szerverről indul (persze ha van csapat, akkor a front-end tervezők elkezdhetnek dolgozni a kliensen). A szerver megvalósításához meglepő módon a TServerSocket-et kell használni.

Alaptulajdonságok:

  • Aktív– logikai típusú mező, ha igaz értékre van állítva – a szerver elindult, használható meghatározott értékek hozzárendelésével és a ServerSocket1.Open (… Active:=true;) vagy ServerSocket1.Close (… Active:=false) meghívásával. funkciókat.
  • kikötő- az a port, amelyen a szerver figyel (klienseket fogad), minden olyan érték, amelyet a rendszerben lévő többi szerver nem foglal el a tartományon belül egész szám.

Fő események:

  • OnListen- akkor hívják meg, ha a szerver figyelési módba van állítva, akkor használható, ha meg kell határoznunk a szerver tényleges kezdési idejét.
  • OnClientRead– hívják az ügyféltől érkező adatok fogadásának pillanatában.
  • OnClientError
  • OnClientConnect- Meghívás, ha új kliens csatlakozik a szerverhez.
  • OnClientDisconnect- az eseménnyel ellentétes esemény, OnClientConnect

minden eseményfüggvénynek van egy attribútuma Aljzat: TCustomWinSocket, egy mutató arra a socket objektumra, amelyben vagyunk Ebben a pillanatban működik, ha válaszolnunk kell valamit vagy tennünk kell valamit az eseményt kiváltó klienssel, akkor ezt az objektumot kell használnunk, minden más esetben ServerSocket1.Socket, a helyzet hasonló a kliens komponenssel is.

Csak olvasható tulajdonságok és függvények:

  • – az aktív kapcsolatok számát adja vissza.
  • ServerSocket1.Socket.Connections– TCustomWinSocket típusú objektumok tömbje, az ügyfelekhez társított összes objektum tömbje, az indexszám 0-tól kezdődik, a tömb hossza egyenlő ServerSocket1.Socket.ActiveConnections.
  • A ServerSocket1.Socket.Connections tömb elemeire és a kiszolgáló eseményfüggvényének átadott Socket attribútumra vonatkozó funkciók és tulajdonságok:
  • Socket.LocalHost
  • Socket.LocalAddress– visszaadja a szerver IP-jét.
  • Socket.RemoteHost
  • Socket.RemoteAddress– visszaadja a kliens IP-jét.
  • Socket.ReceiveText- a klienstől kapott szöveges üzenetet ad vissza, amely után törli a puffert, csak 1 alkalommal használható, 1 fogadásra.
  • Socket.SendText (Szöveg)– Szöveg típusú szöveges üzenetet küld a kliensnek húr.

A TClientSocket komponensnél minden szinte ugyanaz, csak fordítva + a fő vizuális különbség a szerver és a kliens között, a rendszerben lévő szerver 1-1 port értékkel indítható, csak a RAM szab határt a számban. ügyfelek.

Alaptulajdonságok:

  • Aktív– logikai típusú mező, ha igaz értékre van állítva – a kliens megpróbál csatlakozni a szerverhez, használható adott értékek hozzárendelésével és a ClientSocket1.Open (… Active:=true;) vagy ClientSocket1.Close (… Active) meghívásával :=false) függvények .
  • kikötő– port, amelyen a kliens csatlakozhat a szerverhez, bármilyen érték a tartományon belül egész szám.
  • cím– A szervertípus IPv4-címe húr 255.255.255.255 minta, amelyhez az ügyfél csatlakozni fog.

Fő események:

  • OnRead– hívják, amikor északról érkezik adat.
  • OnError- Akkor hívják, ha hiba történik az adatátvitel során.
  • On Connecting- Akkor hívják, amikor az ügyfél csatlakozik a szerverhez.
  • OnDisconnect- az eseménnyel ellentétes esemény, On Connecting, akkor hívják meg, amikor a kliens megszakítja a kapcsolatot a szerverrel.

Csak olvasható tulajdonságok és függvények:

  • ClientSocket1.Socket.SendText() húr
  • Socket.LocalHost– visszaadja a hálózaton lévő kliens nevét.
  • Socket.LocalAddress– visszaadja a kliens IP-jét.
  • Socket.RemoteHost– visszaadja a hálózaton lévő szerver nevét.
  • Socket.RemoteAddress– visszaadja a szerver IP-jét.
  • Socket.ReceiveText– a szervertől kapott szöveges üzenetet ad vissza, ami után törli a puffert, csak 1 alkalommal használható, 1 fogadásra.
  • Socket.SendText (Szöveg)– Szöveg típusú szöveges üzenetet küld a szervernek húr.

A megadott információ elegendő egy kis szervercsevegés megvalósításához, amely kielégíti feladatmeghatározás: internet_sockets.doc (Word Doc 97-2003, 26,5 Kb).

Ez a cikk 2010. október 10-én, vasárnap, 1:24-kor íródott a szekcióban. Feliratkozhat a cikkhez fűzött megjegyzések frissítéseire -. tudsz


Bevezetés


Ez a cikk a socket alapú kliens/szerver alkalmazások létrehozásáról szól a Borland Delphiben ("socket" - fészkeket). A socketekkel foglalkozó korábbi cikktől eltérően itt a szerveralkalmazások létrehozását elemezzük.

Rögtön le kell szögezni, hogy a különálló kliens és szerver alkalmazások együttéléséhez nem szükséges több számítógép. Elég, ha csak egy van, amin egyszerre futtathatod a szervert és a klienst is. Ebben az esetben a gazdagép nevét kell használnia annak a számítógépnek a neveként, amelyhez csatlakozni kíván. helyi kiszolgáló vagy IP cím - 127.0.0.1 .

Kezdjük tehát az elmélettel. Ha Ön egy kitartó gyakorló (és nem lát semmilyen algoritmust a szemével), akkor ezt a részt ki kell hagynia.

Socket szerver algoritmus


Mit csinál egy socket szerver?.. Hogyan működik?.. A socket protokollon alapuló szerver lehetővé teszi, hogy egyszerre több klienst is kiszolgáljon. Ezenkívül saját maga is korlátozhatja a számukat (vagy teljesen eltávolíthatja ezt a korlátozást, ahogy ez alapértelmezés szerint történik). A szerver minden csatlakoztatott klienshez külön socketet nyit, amelyen keresztül adatot cserélhet a klienssel. Szintén remek megoldás, ha minden kapcsolathoz külön folyamatot (Thread) hozunk létre.

A következő példa egy socket szerver működésére mutat be példát a Delphi alkalmazásokban:

Elemezzük részletesebben a sémát:

  • Tulajdonságok meghatározása a Port és a ServerType-ban - ahhoz, hogy a kliensek normálisan kapcsolódhassanak a szerverhez, a szerver által használt portnak pontosan meg kell egyeznie a kliens által használt porttal (és fordítva). A ServerType tulajdonság határozza meg a kapcsolat típusát (a részleteket lásd alább);
  • aljzatnyílás - Socket és a megadott port megnyitása. Itt automatikusan megkezdődik a várakozás a kliensek csatlakozására ( Hallgat);
  • Ügyfél csatlakoztatása és adatcsere vele - itt csatlakozik a kliens és adatcsere történik vele. Erről a szakaszról a cikk későbbi részében és az aljzatokról szóló cikkben (kliensoldal) olvashat bővebben;
  • Ügyfél letiltása - Itt a kliens bontja a kapcsolatot, és megszakad a socket kapcsolata a szerverrel;
  • A szerver és a socket bezárása - Az adminisztrátor parancsára a szerver leállítja a munkáját, bezár minden nyitott socket csatornát, és nem vár a kliens kapcsolatokra.

Megjegyzendő, hogy a 3-4. pontok sokszor ismétlődnek, i.e. ezek az elemek minden új ügyfélkapcsolatnál végrehajtásra kerülnek.

jegyzet : Jelenleg a Delphiben nagyon kevés dokumentáció található a socketekről, ezért ha minél mélyebben szeretnéd tanulmányozni ezt a témát, akkor azt tanácsolom, hogy nézd át a szakirodalmat és az elektronikus dokumentációt a Unix/Linux rendszerekről - ott Nagyon Az aljzatokkal végzett munka elmélete jól le van írva. Ezen túlmenően sok példa van a socket alkalmazásokra ezekhez az operációs rendszerekhez (de leginkább C/C++ és Perl nyelven).

A TServerSocket komponens rövid leírása


Itt fogunk megismerni fő- a komponens tulajdonságai, módszerei és eseményei TServerSocket.

Tulajdonságok

Foglalat - a TServerWinSocket osztály, amelyen keresztül hozzáférhet a nyitott socket csatornákhoz. A továbbiakban ezt a tulajdonságot fogjuk részletesebben megvizsgálni, mert. valójában az egyik fő. Típus: TServerWinSocket ;
Szervertípus - szerver típusa. Két érték egyikét veheti fel: stNonBlocking- szinkron munkavégzés kliens socketekkel. Ezzel a típusú szerverrel eseményeken keresztül dolgozhat az ügyfelekkel OnClientReadÉs OnClientWrite. stThreadBlocking- aszinkron típus. Minden kliens socket csatornához külön folyamat (Thread) jön létre. Típus: TServerType ;
ThreadCacheSize - a szerver által gyorsítótárazott kliens folyamatok (szál) száma. Itt kell kiválasztania az átlagos értéket a szerver terhelésétől függően. A gyorsítótárazás azért történik, hogy ne hozzon létre minden alkalommal külön folyamatot, és ne ölje meg a zárt socketet, hanem hagyja őket további felhasználásra. Típus: Egész szám ;
Aktív - annak jelzése, hogy a szerver jelenleg aktív-e vagy sem. Ez tulajdonképpen az érték Igaz jelzi, hogy a szerver fut és készen áll az ügyfelek fogadására, és Hamis- a szerver ki van kapcsolva. A szerver elindításához csak be kell állítania ezt a tulajdonságot Igaz. Típus: Boolean ;
kikötő - portszám az ügyfelekkel való kapcsolatok kialakításához. A szerver és a kliensek portjának meg kell egyeznie. Az 1025 és 65535 közötti értékek ajánlottak, mint 1-től 1024-ig - a rendszer elfoglalhatja. Típus: Egész szám ;
Szolgáltatás - a szolgáltatást meghatározó karakterlánc ( ftp, http, pop stb.), amelynek portját használni fogják. Ez egyfajta referenciakönyv a portszámok különböző szabványos protokollokhoz való illesztéséhez. Típus: húr ;

nyisd ki - Elindítja a szervert. Ez a parancs lényegében megegyezik az érték hozzárendelésével Igaz ingatlan Aktív;
Bezárás - Leállítja a szervert. Ez a parancs lényegében megegyezik az érték hozzárendelésével Hamis ingatlan Aktív.

OnClientConnect - akkor fordul elő, ha egy kliens socket kapcsolatot létesített, és válaszra vár a szervertől ( OnAccept);
OnClientDisconnect - akkor fordul elő, ha a kliens lekapcsol a socket csatornáról;
OnClientError - akkor fordul elő, ha az aktuális művelet meghiúsult, pl. Hiba történt;
OnClientRead - akkor fordul elő, ha a kliens bizonyos adatokat küldött a szervernek. Ezek az adatok az átadott paraméteren keresztül érhetők el Aljzat: TCustomWinSocket;
OnClientWrite - akkor fordul elő, amikor a szerver adatokat küldhet a socketen lévő kliensnek;
OnGetSocket - ennek az eseménynek a kezelőjében szerkesztheti a paramétert ClientSocket;
OnGetThread - ennek az eseménynek a kezelőjében minden egyes kliens csatornához egyedi folyamatot (Thread) határozhat meg a paraméter beállításával SocketThread a kívánt TServerClientThread részfeladat;
OnThreadStart , OnThreadEnd - egy részfeladat (folyamat, Thread) elindulásakor, illetve leállásakor következik be;
OnAccept - akkor fordul elő, amikor a szerver elfogad egy klienst, vagy megtagadja a kapcsolatot;
OnListen - Akkor fordul elő, amikor a szerver az ügyfelek csatlakozására váró üzemmódba lép.


TServerSocket.Socket(TServerWinSocket)


Tehát hogyan tud egy szerver adatokat küldeni egy kliensnek? Mi a helyzet az adatok fogadásával? Alapvetően ha eseményeken dolgozol OnClientReadÉs OnClientWrite, akkor a ClientSocket (TCustomWinSocket) paraméteren keresztül kommunikálhat az ügyféllel. Az ezzel az osztállyal való munkavégzésről a kliens socketekről szóló cikkben olvashat. Az adatok küldése/küldése ezen az osztályon keresztül hasonló - metódusok (Küldés/Fogadás) (Szöveg, Buffer, Stream). Akkor is, ha a TServerSocket.Socket programmal dolgozik. Mivel azonban Mivel szervert tervezünk, néhány hasznos tulajdonságot és módszert érdemes kiemelni:

  • ActiveConnections (Egész szám) - csatlakoztatott ügyfelek száma;
  • ActiveThreads (Egész szám) a futó folyamatok száma;
  • Kapcsolatok (sor) egy tömb, amely minden egyes csatlakoztatott klienshez egyedi TClientWinSocket osztályokat tartalmaz. Például ez a parancs:
    ServerSocket1.Socket.Connections.SendText("Helló!");
    „Hello!” üzenetet küld az elsőként csatlakoztatott kliensnek. A tömb elemeivel való munkavégzésre szolgáló parancsok is (Küldés/Fogadás)(Szöveg,Buffer, Stream);
  • IdleThreads (Egész szám) a szabad folyamatok száma. Az ilyen folyamatokat a szerver gyorsítótárazza (lásd ThreadCacheSize);
  • helyi cím, helyi kiszolgáló, helyi kikötő- ill. helyi IP-cím, gazdagépnév, port;
  • távoli cím, távoli gazdagép, távoli port- rendre - távoli IP-cím, gazdagépnév, port;
  • Mód zárÉs kinyit- egy aljzat blokkolása és feloldása.

Gyakorlat és példák


Most fontolja meg a fentieket konkrét példa. A kész forrásokat a gombra kattintva töltheti le.

Nézzünk tehát egy nagyon jó példát a TServerSockettel való munkavégzésre (ez a példa a leginkább vizuális segédeszköz ennek az összetevőnek a megtanulásához). Az alábbi forráskód bemutatja az összes fontos szerveresemény naplózását, valamint a fogadási és küldési képességet szöveges üzenetek:

1. példa Fakitermelés és tanulás szerver munka, üzenetek küldése/fogadása aljzatokon keresztül

(... Itt jön a fájl fejléce és a TForm1 űrlap definíciója és Form1 példánya)
(Lásd a teljes forrást)
eljárás TForm1.Button1Click(Sender: TObject); kezdődik (Meghatározzuk a portot és elindítjuk a szervert) ServerSocket1.Port:= 1025; (Az Insert metódus beszúr egy karakterláncot a tömbbe a megadott helyen) Memo2.Lines.Insert(0,"Szerver indul"); ServerSocket1.Open; vége; eljárás TForm1.Button2Click(Sender: TObject); kezdődik (Állítsa le a szervert) ServerSocket1.Active:= False; Memo2.Lines.Insert(0,"Szerver leállt"); vége; procedúra TForm1.ServerSocket1Listen(Sender: TObject; Socket: TCustomWinSocket); kezdődik (Itt a szerver "hallgat" az ügyfelek socketjén) Memo2.Lines.Insert(0,"Hangolás a porton "+IntToStr(ServerSocket1.Port)); vége; procedúra TForm1.ServerSocket1Accept(Sender: TObject; Socket: TCustomWinSocket); kezdődik (Itt a szerver elfogadja a klienst) Memo2.Lines.Insert(0,"Kliens kapcsolat elfogadva"); vége; eljárás TForm1.ServerSocket1ClientConnect(Küldő: TObject; Socket: TCustomWinSocket); kezdődik (Itt csatlakozik a kliens) Memo2.Lines.Insert(0,"Kliens csatlakoztatva"); vége; eljárás TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); kezdődik (Itt a kliens megszakad) Memo2.Lines.Insert(0,"A kliens megszakadt"); vége; eljárás TForm1.ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TERrorEvent; var ErrorCode: Integer); kezdődik (Hiba történt – nyomtassa ki a kódját) Memo2.Lines.Insert(0,"Kliens hiba. Code = "+IntToStr(ErrorCode)); vége; eljárás TForm1.ServerSocket1ClientRead(Küldő: TObject; Socket: TCustomWinSocket); kezdődik (Üzenet érkezett a klienstől - megjelenítjük a Memo1-ben) Memo2.Lines.Insert(0,"Üzenet érkezett az ügyféltől"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); vége; procedúra TForm1.ServerSocket1ClientWrite(Sender: TObject; Socket: TCustomWinSocket); kezdődik (Most már adatokat küldhet az aljzatba) Memo2.Lines.Insert(0,"Most írhat a socketbe"); vége; procedúra TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer; var ClientSocket: TServerClientWinSocket); begin Memo2.Lines.Insert(0,"Socket lekérése"); vége; eljárás TForm1.ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin Memo2.Lines.Insert(0,"Szál lekérése"); vége; eljárás TForm1.ServerSocket1ThreadEnd(Sender: TObject; Szál: TServerClientThread); begin Memo2.Lines.Insert(0,"Szál vége"); vége; eljárás TForm1.ServerSocket1ThreadStart(Küldő: TObject; Szál: TServerClientThread); begin Memo2.Lines.Insert(0,"Szál indítása"); vége; eljárás TForm1.Button3Click(Sender: TObject); var i: Integer; kezdődik (Üzenet küldése MINDEN ügyfélnek az Edit1-től) ha i:= 0 a ServerSocket1.Socket.ActiveConnections-1-hez kezdje a ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); vége; Memo1.Lines.Insert(0,"

Technikák a TServerSocket (és csak a socket) használatához


Egyedi adatok tárolása minden ügyfél számára.


Természetesen, ha a szervere sok klienst fog kiszolgálni, akkor minden klienshez el kell tárolnia néhány információt (név, stb.), és ezeket az információkat a kliens socketéhez kell kötni. Egyes esetekben mindezt manuálisan megtenni (csatlakozás egy socket fogantyúhoz, klienstömbökhöz stb.) nem túl kényelmes. Ezért minden aljzathoz külön tulajdonság tartozik - Adat. Valójában a Data csak egy mutató. Ezért a kliens adatok ebbe a tulajdonságba írásakor legyen körültekintő és tartsa be a pointerekkel való munkavégzés szabályait (memóriafoglalás, típuskövetkeztetés stb.)!

Fájlok küldése aljzaton keresztül.


Itt megnézzük a fájlok socketen keresztüli küldését (a JINX kérésének megfelelően) :-). Tehát hogyan lehet fájlt küldeni egy aljzaton keresztül? Nagyon egyszerű! Csak meg kell nyitnia ezt a fájlt fájlfolyamként (TFileStream), és el kell küldenie socket-en keresztül (SendStream)! Nézzük ezt egy példával:

Meg kell jegyezni, hogy a módszer sendstream nem csak a szerver, hanem a kliens is használja ( ClientSocket1.Socket.SendStream(srcfile))

Miért lehet több blokkot egyesíteni egyetlen átvitel során?


Ezt a JINX is kéri :-). Nagyon köszönöm ezt neki! Tehát először is meg kell jegyezni, hogy a socketen keresztül küldött adatok nem csak egy blokkba vonhatók össze, hanem több blokkra is szétválaszthatók. A helyzet az, hogy a socket egy normál adatfolyam, de ellentétben mondjuk egy fájlfolyammal (TFileStream), lassabban továbbítja az adatokat (érted - a hálózat, korlátozott forgalom stb.). Ezért két parancs:
ServerSocket1.Socket.Connections.SendText("Szia, ");
ServerSocket1.Socket.Connections.SendText("világ!");
teljesen azonosak egy paranccsal:
ServerSocket1.Socket.Connections.SendText("Szia, világ!");

És ezért, ha elküld egy fájlt, mondjuk 100 Kb-ot, a socketen keresztül, akkor az a személy, akinek ezt a blokkot elküldte, több blokkot kap, amelyek mérete a forgalomtól és a vonalterheléstől függ. Ráadásul a méreteknek nem kell azonosnak lenniük. Ebből következik, hogy egy fájl vagy bármilyen más adat fogadásához nagy méretű, Vegyen adatblokkokat, majd egyesítse őket egy egésszé (és mentse például egy fájlba). Kiváló megoldás erre a problémára ugyanaz a fájlfolyam - TFileStream (vagy egy adatfolyam a memóriában - TMemoryStream). Adatrészecskéket fogadhat a socketből az OnRead (OnClientRead) eseményen keresztül, az univerzális módszerrel ReceiveBuf. A módszerrel meghatározhatja a kapott blokk méretét ReceiveLength. Használhat socket adatfolyamot is (lásd a TClientSocket cikket). És itt van egy kis példa (hozzávetőleges):

Hogyan figyeljünk egy aljzatot


Ez a kérdés összetett és hosszas mérlegelést igényel. Egyelőre csak annyit jegyzem meg, hogy a programod által létrehozott socketet mindig figyelheted :-). A socketek (mint a legtöbb Windows objektum) saját fogantyúval (fogantyúval) rendelkeznek, amely a Handle tulajdonságban található. Tehát, miután megtanulta ezt a leírót, szabadon vezérelhet bármilyen aljzatot (még azokat is, amelyeket valaki más programja hozott létre)! Valószínűleg azonban a WinAPI Sockets függvényeket kell használnia valaki más socketjének figyeléséhez.


Ez a cikk bemutatja a Delphi TServerSocket összetevőjének használatához szükséges alapvető trükköket, valamint néhány általános trükköt a socketeken keresztüli kommunikációhoz. Ha bármilyen kérdése van - küldje el nekem e-mailben: [e-mail védett], és még jobb - írjon ennek az oldalnak a fórumába (Delphi. Általános kérdések), hogy a többi felhasználó láthassa kérdését, és megpróbáljon válaszolni rá!

Karikh Nikolai ( Nitro). Moszkva régió, Zsukovszkij

Ez a cikk a socket alapú kliens/szerver alkalmazások létrehozásáról szól a Borland Delphiben. A socketekkel foglalkozó korábbi cikktől eltérően itt a szerveralkalmazások létrehozását elemezzük.
Rögtön le kell szögezni, hogy a különálló kliens és szerver alkalmazások együttéléséhez nem szükséges több számítógép. Elég, ha csak egy van, amin egyszerre futtathatod a szervert és a klienst is. Ebben az esetben a localhost gazdagépnevet vagy az IP-címet - 127.0.0.1 kell használnia annak a számítógépnek a neveként, amelyhez csatlakozni kíván.
Kezdjük tehát az elmélettel. Ha Ön egy kitartó gyakorló (és nem lát semmilyen algoritmust a szemével), akkor ezt a részt ki kell hagynia.
Socket szerver algoritmus
Mit csinál egy socket szerver?.. Hogyan működik?.. A socket protokollon alapuló szerver lehetővé teszi, hogy egyszerre több klienst is kiszolgáljon. Ezenkívül saját maga is korlátozhatja a számukat (vagy teljesen eltávolíthatja ezt a korlátozást, ahogy ez alapértelmezés szerint történik). A szerver minden csatlakoztatott klienshez külön socketet nyit, amelyen keresztül adatot cserélhet a klienssel. Szintén remek megoldás, ha minden kapcsolathoz külön folyamatot (Thread) hozunk létre.
A következő példa egy socket szerver működésére mutat be példát a Delphi alkalmazásokban:

Nézzük meg részletesebben a sémát: · A Port és ServerType tulajdonságok meghatározása - ahhoz, hogy a kliensek normálisan kapcsolódhassanak a szerverhez, a szerver által használt portnak pontosan meg kell egyeznie a kliens által használt porttal (és fordítva ). A ServerType tulajdonság határozza meg a kapcsolat típusát (a részleteket lásd alább); · Nyitott aljzat – nyissa ki a foglalatot és a megadott portot. Itt a kliensek csatlakozásra várásának automatikus elindítása (Listen) történik; · Kliens csatlakoztatása és adatcsere vele - itt egy kliens kapcsolódik és adatcsere történik vele. Erről a szakaszról a cikk későbbi részében és az aljzatokról szóló cikkben (kliensoldal) olvashat bővebben; · Client Disconnect – Itt megszakad a kliens kapcsolata, és megszakad a socket kapcsolata a szerverrel; · A szerver és a socket bezárása – Az adminisztrátor parancsára a kiszolgáló leáll, bezár minden nyitott socket csatornát, és nem vár az ügyfélkapcsolatokra.
Megjegyzendő, hogy a 3-4. pontok sokszor ismétlődnek, i.e. ezek az elemek minden új ügyfélkapcsolatnál végrehajtásra kerülnek.
Megjegyzés: A Delphiben jelenleg nagyon kevés dokumentáció található a socketekkel kapcsolatban, ezért ha ezt a témát a lehető legmélyebben szeretné tanulmányozni, azt tanácsolom, hogy tekintse át a szakirodalmat és az elektronikus dokumentációt a Unix / Linux rendszerekről - a munka elméletéről. ott nagyon jól le van írva az aljzatok. Ezen túlmenően sok példa van a socket alkalmazásokra ezekhez az operációs rendszerekhez (de leginkább C/C++ és Perl nyelven).
A TServerSocket komponens rövid leírása
Itt megismerkedünk a komponens főbb tulajdonságaival, módszereivel és eseményeivel.
Tulajdonságok
Socket - TServerWinSocket osztály, amelyen keresztül hozzáférhet a nyitott socket csatornákhoz. A továbbiakban ezt a tulajdonságot fogjuk részletesebben megvizsgálni, mert. valójában az egyik fő. Típus: TServerWinSocket;
ServerType – szerver típusa. Két érték közül választhat: stNonBlocking – szinkron munka a kliens socketekkel. Az ilyen típusú kiszolgálókkal az OnClientRead és OnClientWrite eseményeken keresztül dolgozhat az ügyfelekkel. Az stThreadBlocking aszinkron típus. Minden kliens socket csatornához külön folyamat (Thread) jön létre. Típus: TServerType;
ThreadCacheSize – a szerver által gyorsítótárazott ügyfélfolyamatok (Thread) száma. Itt kell kiválasztania az átlagos értéket a szerver terhelésétől függően. A gyorsítótárazás azért történik, hogy ne hozzon létre minden alkalommal külön folyamatot, és ne ölje meg a zárt socketet, hanem hagyja őket további felhasználásra. Típus: Integer;
Aktív – jelzi, hogy a szerver jelenleg aktív-e vagy sem. Valójában a True érték azt jelzi, hogy a szerver fut, és készen áll az ügyfelek fogadására, és a False - a szerver ki van kapcsolva. A szerver elindításához csak ezt a tulajdonságot True értékre kell állítani. Típus: Boolean
Port - portszám az ügyfelekkel való kapcsolatok létrehozásához. A szerver és a kliensek portjának meg kell egyeznie. Az 1025 és 65535 közötti értékek ajánlottak, mint 1-től 1024-ig - a rendszer elfoglalhatja. Típus: Integer;
Service - egy karakterlánc, amely megadja a szolgáltatást (ftp, http, pop stb.), amelynek portját használni fogják. Ez egyfajta referenciakönyv a portszámok különböző szabványos protokollokhoz való illesztéséhez. Típus: string
Mód
Megnyitás – Elindítja a szervert. Ez a parancs lényegében megegyezik az Aktív tulajdonság True értékének beállításával;
Bezárás – Leállítja a szervert. Ez a parancs lényegében megegyezik az Active tulajdonság False értékének beállításával.
Események
OnClientConnect – akkor fordul elő, amikor az ügyfél socket-kapcsolatot létesített, és a szerver válaszára vár (OnAccept);
OnClientDisconnect – Akkor jelenik meg, amikor egy kliens leválasztotta a kapcsolatot egy socket csatornáról.
OnClientError – Akkor jelenik meg, ha az aktuális művelet meghiúsult, pl. Hiba történt;
OnClientRead – akkor aktiválódik, amikor a kliens néhány adatot küldött a bervernek. Ezek az adatok a mellékelt Socket paraméteren keresztül érhetők el: TCustomWinSocket;
OnClientWrite – akkor fordul elő, amikor a szerver adatokat küldhet a socketen lévő kliensnek;
OnGetSocket - ebben az eseménykezelőben szerkesztheti a ClientSocket paramétert;
OnGetThread - ennek az eseménynek a kezelőjében egyedi folyamatot (Thread) definiálhat minden különálló klienscsatornához úgy, hogy hozzárendeli a szükséges TServerClientThread részfeladatot a SocketThread paraméterhez;
OnThreadStart, OnThreadEnd - akkor fordul elő, amikor egy részfeladat (folyamat, szál) elindul vagy leáll;
OnAccept – akkor aktiválódik, amikor a szerver elfogadja vagy megtagadja a kapcsolatot egy ügyféllel;
OnListen – Akkor jelenik meg, amikor a szerver az ügyfelek csatlakozására vár.
TServerSocket.Socket(TServerWinSocket)
Tehát hogyan tud egy szerver adatokat küldeni egy kliensnek? Mi a helyzet az adatok fogadásával? Alapvetően, ha az OnClientRead és OnClientWrite eseményeken keresztül dolgozik, akkor a ClientSocket (TCustomWinSocket) paraméteren keresztül kommunikálhat az ügyféllel. Az ezzel az osztállyal való munkavégzésről a kliens socketekről szóló cikkben olvashat. Az adatok küldése/küldése ezen az osztályon keresztül hasonló - metódusok (Küldés/Fogadás) (Szöveg, Buffer, Stream). Akkor is, ha a TServerSocket.Socket programmal dolgozik. Mivel azonban itt egy szerverre gondolunk, néhány hasznos tulajdonságot és módszert érdemes kiemelni: ActiveConnections (Integer) - a csatlakoztatott kliensek száma; ActiveThreads (Integer) - a futó folyamatok száma; ·Kapcsolatok (tömb) - egy tömb, amely külön TClientWinSocket osztályokból áll minden egyes csatlakoztatott klienshez. Például a következő parancs: ServerSocket1.Socket.Connections.SendText("Hello!"); "Hello!" üzenetet küld az első csatlakoztatott kliensnek. A tömb elemeivel való munkavégzésre szolgáló parancsok is (Küldés/Fogadás)(Szöveg,Buffer, Stream); ·IdleThreads (Integer) – a tétlen folyamatok száma. Az ilyen folyamatokat a szerver gyorsítótárazza (lásd ThreadCacheSize); LocalAddress, LocalHost, LocalPort - rendre - helyi IP cím, hosztnév, port; ·RemoteAddress, RemoteHost, RemotePort - rendre - távoli IP-cím, gazdagépnév, port; ·Módszerek Lock és Unlock – egy aljzat blokkolása és feloldása.
Gyakorlat és példák
Most nézzük meg a fentieket egy konkrét példával. A kész forrásokat ide kattintva töltheti le.
Nézzünk tehát egy nagyon jó példát a TServerSockettel való munkavégzésre (ez a példa a leginkább vizuális segédeszköz ennek az összetevőnek a megtanulásához). Az alábbi források bemutatják az összes fontos szerveresemény naplózását, valamint a szöveges üzenetek fogadásának és küldésének lehetőségét:
1. példa: Naplózás és a szerver munkájának tanulmányozása, üzenetek küldése/fogadása socketeken keresztül.

(... Itt jön a fájl fejléce és a TForm1 űrlap definíciója és Form1 példánya)

(A teljes forrást lásd itt)

eljárás TForm1.Button1Click (Küldő: TObject ) ;

kezdődik

(Meghatározzuk a portot és elindítjuk a szervert)

ServerSocket1.Port := 1025 ;

(Az Insert metódus beszúr egy karakterláncot a tömbbe a megadott helyen)

Memo2.Lines .Insert (0 "Szerver indul" ) ;

ServerSocket1.Open ;

vége ;

eljárás TForm1.Button2Click (Feladó: TObject ) ;

kezdődik

(Állítsa le a szervert)

ServerSocket1.Active := False ;

Memo2.Lines .Insert (0 ,,Szerver leállt" ) ;

vége ;

procedúra TForm1.ServerSocket1Listen(Sender: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Itt a szerver "hallgat" az ügyfelek socketjén)

Memo2.Lines .Insert (0 ,"Listening on port " +IntToStr (ServerSocket1.Port ) ) ;

vége ;

procedúra TForm1.ServerSocket1Accept(Sender: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Itt a szerver elfogadja a klienst)

Memo2.Lines .Insert (0 "Kliens kapcsolat elfogadva" ) ;

vége ;

eljárás TForm1.ServerSocket1ClientConnect(Küldő: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Itt csatlakozik a kliens)

Memo2.Lines .Insert (0 "Kliens csatlakoztatva" ) ;

vége ;

procedúra TForm1.ServerSocket1ClientDisconnect(Sender: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Itt a kliens megszakad)

Memo2.Lines .Insert (0 ,Kliens leválasztva) ;

vége ;

eljárás TForm1.ServerSocket1ClientError (Feladó: TObject ;

Socket: TCustomWinSocket; ErrorEvent: TERrorEvent;

var ErrorCode: Integer);

kezdődik

(Hiba történt – nyomtassa ki a kódját)

Memo2.Lines .Insert (0 ,"Client error. Code = " +IntToStr (ErrorCode) ) ;

vége ;

eljárás TForm1.ServerSocket1ClientRead(Küldő: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Üzenet érkezett a klienstől - megjelenítjük a Memo1-ben)

Memo2.Lines .Insert (0, "Üzenet érkezett az ügyféltől") ;

Memo1.Lines .Insert (0 ,"> " +Socket.ReceiveText ) ;

vége ;

procedúra TForm1.ServerSocket1ClientWrite(Sender: TObject ;

Socket: TCustomWinSocket) ;

kezdődik

(Most már adatokat küldhet az aljzatba)

Memo2.Lines .Insert (0 "Most már írhat a socketbe" ) ;

vége ;

eljárás TForm1.ServerSocket1GetSocket (Sender: TObject ; Socket: Integer ;

var ClientSocket: TServerClientWinSocket) ;

kezdődik

Memo2.Lines .Insert (0 "Cet socket" ) ;

vége ;

procedúra TForm1.ServerSocket1GetThread(Sender: TObject ;

ClientSocket: TServerClientWinSocket;

varSocketThread: TServerClientThread) ;

kezdődik

Memo2.Lines .Insert (0 "Szál lekérése" ) ;

vége ;

eljárás TForm1.ServerSocket1ThreadEnd (Küldő: TObject ;

kezdődik

Memo2.Lines .Insert (0 "Szálvég" ) ;

vége ;

procedúra TForm1.ServerSocket1ThreadStart(Sender: TObject ;

Szál: TServerClientThread) ;

kezdődik

Memo2.Lines .Insert (0 "Szál indítása" ) ;

vége ;

eljárás TForm1.Button3Click (Feladó: TObject ) ;

var i: Integer ;

kezdődik

(Üzenet küldése MINDEN ügyfélnek az Edit1-től)

i:= 0 esetén a ServerSocket1.Socket.ActiveConnections -1 -1 esetén kezdődik

ServerSocket1.Socket .Kapcsolatok [i] .SendText (Edit1.Text ) ;

vége ;

Memo1.Lines .Insert(0,"< " +Edit1.Text ) ;

vége ;

Továbbá többé nem példákat fogunk figyelembe venni, hanem a TServerSockettel való munkamódszereket.
Technikák a TServerSocket (és csak a socket) használatához
Egyedi adatok tárolása minden ügyfél számára.
Természetesen, ha a szervere sok klienst fog kiszolgálni, akkor minden klienshez el kell tárolnia néhány információt (név, stb.), és ezeket az információkat a kliens socketéhez kell kötni. Egyes esetekben mindezt manuálisan megtenni (csatlakozás egy socket fogantyúhoz, klienstömbökhöz stb.) nem túl kényelmes. Ezért minden aljzathoz van egy speciális tulajdonság - Adat. Valójában a Data csak egy mutató. Ezért a kliens adatok ebbe a tulajdonságba írásakor legyen körültekintő és tartsa be a pointerekkel való munkavégzés szabályait (memóriafoglalás, típuskövetkeztetés stb.)!
Fájlok küldése aljzaton keresztül.
Itt megnézzük a fájlok socketen keresztüli küldését (a JINX kérésének megfelelően) :-). Tehát hogyan lehet fájlt küldeni egy aljzaton keresztül? Nagyon egyszerű! Csak meg kell nyitnia ezt a fájlt fájlfolyamként (TFileStream), és el kell küldenie socket-en keresztül (SendStream)! Nézzük ezt egy példával:

(Fájl küldése socketen keresztül)

procedúra SendFileBySocket(fájlnév: string ) ;

var srcfile: TFileStream;

kezdődik

(Fájlnév megnyitása)

Srcfile:= TFileStream.Create (fájlnév,fmOpenRead) ;

(Küldje el az első csatlakoztatott kliensnek)

ServerSocket1.Socket .Connections [ 0 ] .SendStream(srcfile) ;

(Zárja be a fájlt)

Srcfile.Free ;

vége ;

Megjegyzendő, hogy a SendStream metódust nem csak a szerver, hanem a kliens is használja (ClientSocket1.Socket.SendStream(srcfile))
Miért lehet több blokkot egyesíteni egyetlen átvitel során?
Ezt a JINX is kéri :-). Nagyon köszönöm ezt neki! Tehát először is meg kell jegyezni, hogy a socketen keresztül küldött adatok nem csak egy blokkba vonhatók össze, hanem több blokkra is szétválaszthatók. A helyzet az, hogy a socket egy normál adatfolyam, de ellentétben mondjuk egy fájlfolyammal (TFileStream), lassabban továbbítja az adatokat (érted - a hálózat, korlátozott forgalom stb.). Ezért két parancs:
ServerSocket1.Socket.Connections.SendText("Szia, ");
ServerSocket1.Socket.Connections.SendText("világ!");
teljesen azonosak egy paranccsal:
ServerSocket1.Socket.Connections.SendText("Szia, világ!");
És ezért, ha elküld egy fájlt, mondjuk 100 Kb-ot, a socketen keresztül, akkor az a személy, akinek ezt a blokkot elküldte, több blokkot kap, amelyek mérete a forgalomtól és a vonalterheléstől függ. Ráadásul a méreteknek nem kell azonosnak lenniük. Ebből következik, hogy egy fájl vagy bármilyen más nagy adat fogadásához adatblokkokat kell fogadnia, majd ezeket egy egésszé kell egyesíteni (és például fájlba menteni). Kiváló megoldás erre a problémára ugyanaz a fájlfolyam - TFileStream (vagy egy adatfolyam a memóriában - TMemoryStream). Adatrészecskéket fogadhat a socketből az OnRead (OnClientRead) eseményen keresztül, a ReceiveBuf univerzális módszerrel. A fogadott blokk méretét a ReceiveLength módszerrel határozhatja meg. Használhat socket adatfolyamot is (lásd a TClientSocket cikket). És itt van egy kis példa (hozzávetőleges):

(Fájl fogadása socketen keresztül)

procedúra TForm1.ClientSocket1Read(Küldő: TObject ;

Socket: TCustomWinSocket) ;

varl: Integer ;

Buf: PChar ;

Src: TFileStream;

kezdődik

(l-be írjuk a kapott blokk méretét)

L:= Socket.ReceiveLength ;

(Memóriát rendelünk a pufferhez)

GetMem (buf,l+1 );

(A kapott blokkot a pufferbe írjuk)

Socket.ReceiveBuf(buf,l) ;

(Nyiss meg egy ideiglenes fájlt íráshoz)

Src:= TFileStream.Create("sajátfájl.tmp" ,fmOpenReadWrite) ;

(Tegye a pozíciót a fájl végére)

Src.Seek(0,soFromEnd) ;

(Puffer írása a fájlba)

Src.WriteBuffer(buf,l) ;

(Zárja be a fájlt)

Src.Free ;

(Memória felszabadítása)

FreeMem (buf) ;

vége ;

Hogyan figyeljünk egy aljzatot
Ez a kérdés összetett és hosszas mérlegelést igényel. Egyelőre csak annyit jegyzem meg, hogy a programod által létrehozott socketet mindig figyelheted :-). A socketek (mint a legtöbb Windows objektum) saját fogantyúval (fogantyúval) rendelkeznek, amely a Handle tulajdonságban található. Tehát, miután megtanulta ezt a leírót, szabadon vezérelhet bármilyen aljzatot (még azokat is, amelyeket valaki más programja hozott létre)! Valószínűleg azonban a WinAPI Sockets függvényeket kell használnia valaki más socketjének figyeléséhez.
Epilógus
Ez a cikk bemutatja a Delphi TServerSocket összetevőjének használatához szükséges alapvető trükköket, valamint néhány általános trükköt a socketeken keresztüli kommunikációhoz. Ha bármilyen kérdése van - küldje el nekem e-mailben: [e-mail védett], és még jobb - írjon ennek az oldalnak a fórumába (Delphi. Általános kérdések), hogy a többi felhasználó láthassa kérdését, és megpróbáljon válaszolni rá!
Karikh Nikolay (Nitro). Moszkva régió, Zsukovszkij

Hozzáadtam a hálózati támogatást. Ezzel létrejön a külön szerver és a különálló kliens. A lényeg az, hogy az alkalmazásszerver fut, a felhasználó elindítja a klienst, és beírja a kérést a felhasználóba: Moscow Tverskaya 6. Ezután a szerver feldolgozza a kérést, megkapja a keresési eredményeket a Yandex.Maps-től és a kapott képet elküldi a kliensnek. , akkor megjelenik a kliensben a TMap komponens adott kártyáján az a rész, amelyik megfelel a felhasználó kérésének. Ennek eredményeként a felhasználó méretezheti, elmentheti stb.

Ezért ebben a cikkben szeretném elmondani, hogyan implementáltam a klienst és a szervert. Ezt a TClientSocket és a TServerSocket segítségével tettem, ebben a cikkben részletesen megvizsgáljuk azokat a módszereket, amelyeket a projektemben használtam.

Először is nézzük meg, hogyan telepíthetők ezek az összetevők az IDE-be. Ha Delphi 7 IDE-t használ, akkor ezek az összetevők alapértelmezés szerint jelen vannak, de sajnos nincsenek telepítve, de ez nem probléma. Csak meg kell nyitnunk a Delphi-t és telepítenünk kell.

Ehhez futtassa a Component-Install Packages… parancsot, és a megjelenő ablakban kattintson a Hozzáadás gombra. Ezt követően meg kell adnia a dclsockets70.bpl fájl elérési útját, amely alapértelmezés szerint általában a BIN mappában található. Ezt követően az OK gombra kell kattintania. Mindennek, az összetevőknek meg kell jelenniük az Internet lapon (TClientSocket és TServerSocket).

A projektben minden munkát elkezdtem, minimális szerverfejlesztéssel. Először a TServerSocket összetevőt telepítettem az űrlapra. És a Kiszolgáló indítása gombra kattintva állítsa be kezdeti beállítások, inicializálásához:

szerver. Port := FormServerSetting. SpinEditPort. érték; //adja meg a kiszolgáló portját szerver. Aktív := Igaz ; //aktiválja Szerver. nyisd ki; ifServer. Aktív, majd kezdje el //üzenet megjelenítése arról, hogy a kiszolgáló működik és működik vége ; …….. //hiba jelenik meg, ha a szerver nem indult el

A szerver inicializálásához a gépemen csak egy szabad portot állítottam be (amit más alkalmazások nem foglalnak el) és aktiváltam.

Elvileg ennyi, nekem a munkához elég volt, hogy fut a szerver és fel tudtam dolgozni a kliensek kéréseit amit küldenek.

Annak érdekében, hogy megkapjam a szerverhez csatlakozó kliensek listáját, és tovább dolgozhassak velük, telepítettem a TCheckListBox komponenst az űrlapra és a TServerSocket komponens OnclientConnect eseményére a következő kódot írtam:

eljárás TFormServer. ServerClientConnect (Sender: TObject ; Socket: TCustomWinSocket) ; kezdődik //kliens kapcsolat figyelése richeditlog. SelAttributes. Szín :=clZöld; richeditlog. SelAttributes. Stílus := [fsBold] ; CheckListClient. Tételek. Add(Socket.RemoteHost); richeditlog. Vonalak. Add ("[" + TimeToStr (Time ) + "] Kliens csatlakoztatva: " + Socket. RemoteHost ) ; // hozzáadjuk a listához a csatlakozott klienst richeditlog. Perform(WM_VSCROLL, SB_BOTTOM, 0) ; vége ;

Azaz felveszem a listára azoknak a klienseknek a nevét, amelyek a szerverhez csatlakoznak, hogy további információkat kapjak róluk.

Például kaphat részletes információk az ügyfélről:

eljárás TFormInfoClient. FormShow(Sender: TObject) ; kezdődik // információ nyomtatása az ügyfélről felirat:= "Vásárlói információ: "+ űrlapszerver. CheckListClient. Elemek [FormServer. CheckListClient. ItemIndex] ; helyi név. Felirat := FormServer. Szerver. foglalat. Kapcsolatok [FormServer. CheckListClient. ItemIndex] . Helyi kiszolgáló ; helyi kiszolgáló. Felirat := FormServer. Szerver. foglalat. Kapcsolatok [FormServer. CheckListClient. ItemIndex] . Helyi cím ; helyi kikötő. Caption := IntToStr (FormServer. Server . Socket . Connections [ FormServer. CheckListClient . ItemIndex ] . LocalPort ) ; távoli név. Felirat := FormServer. Szerver. foglalat. Kapcsolatok [FormServer. CheckListClient. ItemIndex] . távoli gazdagép ; remotehost. Felirat := FormServer. Szerver. foglalat. Kapcsolatok [FormServer. CheckListClient. ItemIndex] . Távoli cím ; távoli port. Caption := IntToStr (FormServer. Server . Socket . Connections [ FormServer. CheckListClient . ItemIndex ] . RemotePort ) ; vége ;

A következő adatokat kaphatja meg:

  • helyi név
  • Helyi cím
  • helyi kikötő
  • távoli név
  • távoli cím
  • távoli port

Ezzel a kóddal kapok információkat a kliensről, amelyet a TCheckListBox komponens listájában választottam ki.

Amint látja, nincs semmi bonyolult, az ügyfélnek szóló üzenet küldéséhez a következő kódot használhatja:

BAN BEN szögletes zárójelek, megadom, hogy melyik kliensnek küldjük az üzenetet (ez megegyezik a TCheckListBox komponensben kiválasztott klienssel), az üzenetben megadom a #message#-ot - ami azt jelenti, hogy ez egy normál üzenet a szervertől, amit egyszerűen kell megjelenik az ablakban.

Ahhoz, hogy üzenetet kapjunk a klienstől a szerver felé, szükségünk van a TServerSocket komponens OnClientRead eseményére és egy szöveges változóra, amelybe a kliens által küldött kérést írjuk.

eljárás TFormServer. ServerClientRead(Küldő: TObject ; Socket: TCustomWinSocket) ; var lekérdezés: String ; kezdődik //kérést kap az ügyféltől a kártyára try query:= Socket. ReceiveText ; if pos("lekérdezés", lekérdezés)<>0, majd indítsa el //kérelem a Yandextől vagy Google koordináták kártyákat az ügyfél kérésének megfelelően vége ; //ha csak egy üzenet a klienstől, akkor jelenítse meg if pos("#üzenet#" , lekérdezés)<>0, majd kezdés vége ; ……

Ebből a kódból láthatja, hogy az ügyfél normál üzenetet és kártyakérést is küldhet a szervernek, például: Moszkva, Tverskaya, 6.

Ehhez meg kell határoznom, hogy hol van a szokásos üzenet, és pontosan hol van a kártya átvételi kérése, hogy a szerver a jövőben feldolgozhassa. Ebben az esetben a legelején a következő azonosítókat adom hozzá a kliens üzeneteihez:

  • #üzenet#
  • #lekérdezés#

Ha az #message# azonosító szerepel a kliens üzenetének elején, akkor a szerver normál üzenetként ismeri fel az ügyféltől. Ha a #query# azonosító szerepel az üzenet elején, ez azt jelenti, hogy az ügyfél kérelmet küldött kártya fogadására.

Ezenkívül a kliens bármikor lekapcsolhatja a szervert, ezt is nyomon kell követnünk, hogy eltávolítsuk a szerverhez csatlakozó kliensek általános listájáról. Ehhez válassza ki a TServerSocket komponenst, és írja be a következő kódot az OnClientDisconnect eseményhez:

eljárás TFormServer. ServerClientDisconnect (Sender: TObject ; Socket: TCustomWinSocket) ; var i: integer ; kezdje el a próbálkozást //figyelje az ügyfél leállítását richeditlog. SelAttributes. Szín :=clRed; richeditlog. SelAttributes. Stílus := [fsBold] ; for i := 0 a szerverhez. foglalat. ActiveConnections – 1 akkor kezdődik, ha Server. foglalat. Kapcsolatok[i]. Handle = szerver. foglalat. Kapcsolatok[i]. Kezelje, majd indítsa el a RichEditLog alkalmazást. Vonalak. Add ("[" + TimeToStr (Time ) + "] Kliens leválasztva: " + Socket. RemoteHost ) ; CheckListClient. Tételek. Törlés(i) ; richeditlog. Perform(WM_VSCROLL, SB_BOTTOM, 0) ; vége ; vége ; végül //-//-//-//-//-// vége ; vége ;

Végignézzük a listán szereplő összes klienst, és ha nem találunk egyet sem, akkor eltávolítjuk a TCheckListBox komponensből, ami azt jelenti, hogy az alkalmazásában lévő kliens rákattintott a Leválasztás gombra.




Top