Delphi Socket Komponensei

 

A következőkben szeretném bevezetni az olvasót, a Delphiben megismert Client (kliens) és Server (szerver) socket komponensek világába, amiről már rengeteg cikket olvashattunk, de talán ezzel a cikkel a kezdők jobban elindulhatnak és elsajátíthatják a TCP/IP programozás alapjait. A jobb megértéshez egy példaprogramot is mellékelek. Véleményem szerint ez a cikk hasznos lehet azoknak, akik még csak most ismerkednek a Delphivel és a kliens-szerver alkalmazásokkal.

 

Alapjában véve mi is az a TCP/IP kliens?

Egy felhasználói program (alkalmazás), amely meghatározott portra csatlakozik a TCP/IP szerveren keresztül és adatokat cserél akár stream vagy szöveges formátumban.

Mi kell ahhoz hogy létrehozz egy TCP/IP alkalmazást Delphiben?

A legegyszerűbb módja, hogy felveszel egy TClientSocket komponenst - amit az Internet palettán találhatsz meg - és ide állítsd be a következő tulajdonságokat:

Address (cím): Ide annak a TCP/IP szervernek az IP címe kerül, amihez ez a kliens csatlakozik.

Host (hoszt): A cím (address) helyett ide egy alias nevet írhatsz az IP címnek a Host tulajdonságokban. Nyilvánvaló, hogy be kell állítani vagy a címet vagy a host tulajdonságokat. De mi van akkor, ha mindkettő megvan? A host a cím felett áll a beállítás szerint, így ezt nézi elsődlegesen a fordítónk.

A Host tulajdonság beállítása jobb, mint a címé, mert még ha meg is változtatod a TCP/IP szervert egy másik gépre vagy más IP címre váltasz, amíg az alias név megmarad, nem kell megváltoztatni azt a TCP/IP kliensen. (még akkor is ha kissé feleslegesnek tűnik, hogy válaszoljon a host az annak megfelelő IP címre, megéri ha van...)

Port .: Ez egy érvényes integer port szám ahol a TCP/IP szerver figyel és válaszol. Ez mindig egy állandó szám a szerverhez kötve. Ehhez a port számhoz a kliens kapcsolódik, valamint adatot küld/kap.

Service (szolgáltatás).: Mint a host és az address tulajdonságok egyféleképp egymáshoz kötöttek, így Port és Service is. Általánosságban a Service az, amit a TCP/IP szerver nyújt a klienseinek (mint például http, ftp ). Ezek az általános szolgáltatások egy külön porthoz vannak hozzárendelve a szerveren. (pl.: http a port 40-hez). Felmerülhet a kérdés, hogyan működik ez valójában. A szerveren van egy services fájl, amelyben a szolgáltatásokat a viszonylagos portjaikkal mappeli (kapcsolja) össze, így saját szolgáltatás leírásaid lehetnek, amelyek egy meghatározott portra mappelnek (mutatnak) a szerveren. Így a kliens a szolgáltatáshoz tud kapcsolódni, felhasználva a szolgáltatás tulajdonságot és elvégzi a feladatát.

ClientType (kliens típus): Ez a tulajdonság határozza meg, hogy a kölcsönhatás a szerver és a kliens közt szinkron vagy aszinkron módon jön-e létre.

ctNonBlocking (nem blokkoló, alapértelmezett) Ebben az esetben a szerver és kliens között a kölcsönhatás aszinkron, azaz a kliens tud adatot küldeni a szervernek és megvárja az OnRead adat végrehajtódását, amikor az adat a szervertől visszaérkezik.

vtBlocking – (blokkoló) Ez a szerver-kliens közötti kölcsönhatás szinkron módú végrehajtódásához kell.

 

Mikor tegyük a Client Code-ot (kliens kód) szálbiztossá? (thread-safe mód)

Ha több, mint egy kérés küldődik egyidejűleg a kliens alkalmazástól a szerver felé, akkor ajánlott a "client code" thread-safe módba ültetése. Más esetben a kérés-válasz összeomolhat. (request-response)

 

Mikor rakjuk a Server Code-ot thread-safe módba? (szálbiztos mód)

Ha egyidejűleg több mint egy kérés érkezik, akár kliens alkalmazástól, akár különböző kliens alkalmazásoktól, akkor ajánlatos, hogy a "server code" thread-safe módban legyen. Ez általánosan használható minden TCP/IP szerver számára, a programnyelvtől független módon.

 

Melyik a legjobb hely a TClientSocket komponens beépítésére az alkalmazásunkban?

A komponenst teheted DataModule formátumba. Ha csak egy páratlan formátumod van a kliens alkalmazásban, ami a szerverrel kommunikál, akkor nincs probléma a TClientSocket komponenssel ebben a formátumban. De ha sok formátumod van a kliens alkalmazásban, akkor jobb ötlet a komponenst DataModul formátumba rakni és ezt alkalmazni, ahol csak kell.

 

Hogy kapcsolódsz a szerverhez?

Állítsd be az összes tulajdonságot, amit fentebb említettem, majd vagy az aktív tulajdonságot állítsd igazra (active tulajdonság true) vagy használd az Open módot. Amint létrejön a kapcsolat, az adatküldést vagy a SendText vagy a SendStream rutinokkal teheted meg. Ne felejtsd el, hogy az OnClientSocketRead rutint használhatod a szervertől visszaérkező adat olvasására.

 

Mi az a TCP/IP szerver?

Olyan alkalmazás, amely egy meghatározott porton figyel és válaszol a klienseknek. Ez akármilyen általános szerver lehet mint például http, ftp vagy akármilyen másik szerver az egyéni alkalmazásokhoz.

 

Mi kell ahhoz, hogy Delphivel csinálj egyet?

Ugyanúgy, mint a kliens esetén, egy TServerSocket komponens kell a következő beállításokkal:

Port.: Bármely integer adatot írhatsz ide. Ehhez a porthoz a kliens kapcsolódhat és kommunikálhat.

Service: Mint már említettem, a port-hoz kapcsolódóan lehet szolgáltatás neved.

Ha szervert mondunk, akkor több mint egy klienst kellene egyszerre kiszolgálni tudnia, mert csak ekkor van értelme. Most a legfontosabb következő kérdés, hogyan kommunikálnak a kliensek a szerverrel: több kliens egyszerre vagy egy kliens egy időben. Ez egy következő beállítás alkalmazásához vezet, mely meghatározza, hogy a kliensek a szerverrel szinkron vagy aszinkron módon kommunikálnak.

 

Hogyan kezeljük több kliens kérését egyszerre?

A megoldás az, hogy hozzunk létre egy új szálat minden kliens kérésnek. Ez elérhető a ServerType tulajdonság stThreadBlocking értékre állításával. Nem minden új szál létrehozás (spawning) és megszüntetés kell, hogy rendelkezzen megkerülő lehetőséggel (overhead). De ha az alkalmazásunk elrendezése kívánja, akkor kell a megkerülő lehetőség. Felmerülhet a kérdés, csökkenthető-e az overhead szálak létrehozásával és eltüntetésével? A válasz egyértelműen igen. És hogyan? Rejtsd el a szálakat!

A ThreadCacheSize tulajdonság szolgálja ezt a célt. Az alapérték 10, de ez az érték a kliens alkalmazásod igényeitől függ. Ezzel a beállítással vigyázni kell! Ha maxra állítod, memória bajokkal kell szembenézned. Ha túl alacsonyra, a kliensnek várakozási ideje lesz minden kérelemnél. A megoldás a legjobb érték beállítása a kliens statisztikája alapján.
Ha a kliens kérelmek egy időben, egyszerre jönnek, akkor a ServerType tulajdonságot stNonBlockingra állíthatod.

 

Hogy olvasunk vissza adatot a klienstől?

Mint ClientSocket, ott van az OnClientRead rutin, amely visszaolvassa az adatot a klienstől.

 

Nagyjából ennyi lett volna a kliens és szerver socket bemutatása, ha problémád vagy kérdésed van, e-mail útján megteheted.

 

*** Forrás mellékelve – delphi.zip ***

 

Gebei János – ircadmin@aom.hu