V tΘto kapitole se zaΦneme zab²vat vytvß°enφm Internetovsk²ch
a Intranetovsk²ch aplikacφ a distribuovan²ch aplikacφ. Nejd°φve se budeme
zab²vat sokety.
Komponenty soket∙ umo╛≥ujφ vytvß°et aplikace, kterΘ mohou
komunikovat s ostatnφmi systΘmy pomocφ TCP/IP a podobn²ch protokol∙. Pomocφ
soket∙ m∙╛eme Φφst a zapisovat prost°ednictvφm p°ipojenφ na dal╣φ poΦφtaΦ
a to bez nutnosti znalostφ aktußlnφho sφ╗ovΘho software. Sokety poskytujφ
p°ipojenφ zalo╛enΘ na protokolu TCP/IP, ale jsou takΘ urΦeny pro prßci
s podobn²mi protokoly, jako je Xerox Network System (XNS), DECnet firmy
Digital nebo IPX/SPX firmy Novell.
C++ Builder umo╛≥uje zapisovat sφ╗ovΘ servery nebo klientskΘ
aplikace, kterΘ Φtou z nebo zapisujφ na ostatnφ systΘmy. Aplikace serveru
nebo klienta je obvykle vyhrazena k jednΘ slu╛b∞ jako je Hypertext Transfer
Protocol (HTTP) nebo File Transfer Protocol (FTP). Pomocφ soket∙ serveru,
aplikace poskytujφcφ jednu z t∞chto slu╛eb, se m∙╛e spojit s klientskou
aplikacφ, kterß chce pou╛φvat tuto slu╛bu. KlientskΘ sokety umo╛≥ujφ aplikaci
pou╛φvajφcφ jednu z t∞chto slu╛eb, spojenφ se serverovou aplikacφ, kterß
slu╛bu poskytuje.
K zßpisu aplikacφ pou╛φvajφcφch sokety, musφme pochopit:
Implementovßnφ slu╛eb
Sokety poskytujφ jßdro pot°ebnΘ k zßpisu sφ╗ov²ch server∙
a klientsk²ch aplikacφ. Mnoho slu╛eb, jako je HTTP nebo FTP je dob°e dostupn²ch.
N∞kdy jsou slu╛by zabudovanΘ do operaΦnφho systΘmu a tedy nenφ nutnΘ zapisovat
svΘ vlastnφ. NicmΘn∞, kdy╛ po╛adujeme lep╣φ °φzenφ ne╛ poskytuje implementovanß
slu╛ba, t∞sn∞j╣φ integraci mezi na╣φ aplikacφ a sφ╗ovou komunikacφ nebo
kdy╛ po╛adovanß slu╛ba nenφ dostupnß, pak m∙╛eme chtφt vytvo°it svoji vlastnφ
serverovou nebo klientskou aplikaci. Nap°. kdy╛ pracujeme s distribuovanou
datovou mno╛inou, m∙╛eme chtφt zapsat komunikaΦnφ vrstvu s databßzemi na
ostatnφch systΘmech.
K implementaci a pou╛φvßnφ slu╛eb realizovan²ch sokety
se musφme seznßmit s:
Protokoly slu╛eb
D°φve ne╛ m∙╛eme zapisovat aplikaci sφ╗ovΘho serveru nebo
klienta, musφme pochopit slu╛by, kterΘ na╣e aplikace bude poskytovat nebo
pou╛φvat. Mnoho slu╛eb mß standardnφ protokoly, kterΘ na╣e sφ╗ovß aplikace
m∙╛e vyu╛φvat. Pokud zapisujeme sφ╗ovou aplikaci pro standardnφ slu╛bu,
jako je HTTP nebo FTP, musφme nejprve pochopit protokoly pou╛itΘ pro komunikaci
s ostatnφmi systΘmy. Musφme si prohlΘdnout dokumentaci slu╛by, kterou chceme
pou╛φvat.
Pokud poskytujeme novou slu╛bu pro aplikaci, kterß komunikuje
s ostatnφmi systΘmy, pak prvnφm krokem je navr╛enφ komunikaΦnφho protokolu
pro server i klienta tΘto slu╛by. JakΘ zprßvy jsou zasφlßny? Jak jsou tyto
zprßvy koordinovßny? Jak jsou informace zak≤dovßny?
╚asto na╣e aplikace sφ╗ovΘho serveru nebo klienta poskytuje
vrstvu mezi sφ╗ov²m softwarem a aplikacφ, kterß pou╛φvß slu╛by. Nap°. HTTP
server je mezi aplikacφ Web serveru a Internetem, kter² poskytuje p°ipojenφ
a reaguje na zprßvy HTTP.
Sokety poskytujφ rozhranφ mezi na╣im sφ╗ov²m serverem
nebo klientskou aplikacφ a sφ╗ov²m software. Musφ poskytnout rozhranφ mezi
na╣φ aplikacφ a aplikacφ, kterß ji pou╛φvß. M∙╛eme pou╛φt standardnφ slu╛bu
API (jako je ISAPI) nebo m∙╛eme navrhnout a zve°ejnit svΘ vlastnφ API.
Slu╛by a porty
V∞t╣ina standardnφch slu╛eb je spojenß (konvencφ) se specifick²m
Φφslem portu. Kdy╛ implementujeme slu╛bu, pak m∙╛eme pova╛ovat Φφslo portu
jako Φφseln² k≤d slu╛by.
Jestli╛e implementujeme standardnφ slu╛bu, objekty soket∙
Windows poskytujφ metody pro nalezenφ Φφsla portu pro slu╛bu. Pokud poskytujeme
novou slu╛bu, pak m∙╛eme specifikovat p°i°azenΘ Φφslo portu v souboru SERVICES
na poΦφtaΦi s Windows 95 nebo NT. Vφce informacφ o nastavovßnφ souboru
SERVICES nalezneme v dokumentaci Soket∙ Windows.
Typy soketov²ch p°ipojenφ
Soketovß p°ipojenφ m∙╛eme rozd∞lit na t°i zßkladnφ typy,
kterΘ urΦujφ, jak p°ipojenφ bude inicializovßno a k Φemu se p°ipojujeme.
Jsou to:
Pouze p°ipojenφ na klientsk² soket je kompletovßno, jinak
serverovΘ p°ipojenφ je nerozeznatelnΘ od klientskΘho p°ipojenφ. Oba koncovΘ
body majφ stejnΘ mo╛nosti a zφskßvajφ stejnΘ typy udßlostφ. Naslouchacφ
p°ipojenφ se zßsadn∞ li╣φ, mß pouze jeden koncov² bod.
KlientskΘ p°ipojenφ
KlientskΘ p°ipojenφ p°ipojuje klientsk² soket na lokßlnφm
systΘmu k serverovΘmu soketu na vzdßlenΘm systΘmu. Klientskß p°ipojenφ
jsou inicializovßna klientsk²m soketem. Klientsk² soket musφ popisovat
serverov² soket, ke kterΘmu se chceme p°ipojit. Klientsk² soket pak hledß
serverov² soket a kdy╛ server nalezne vy╛aduje p°ipojenφ. Serverov² soket
udr╛uje frontu klientsk²ch po╛adavk∙ a kompletuje p°ipojenφ. Kdy╛ serverov²
soket akceptuje klientskΘ p°ipojenφ, pak serverov² soket, ke kterΘmu se
p°ipojujeme zasφlß sv∙j pln² popis klientskΘmu soketu a p°ipojenφ je klientem
kompletovßno.
Naslouchacφ p°ipojenφ
ServerovΘ sokety nelokalizujφ klienty. Jsou pasivnφ formou
"poloviny p°ipojenφ" kterß naslouchß klientsk²m po╛adavk∙m. ServerovΘ sokety
p°i°azujφ frontu ke sv²m naslouchacφm p°ipojenφm; fronta zaznamenßvß po╛adavky
klient∙ na p°ipojenφ jak p°ichßzejφ. Kdy╛ serverov² soket akceptuje po╛adavek
na klientskΘ p°ipojenφ, provedeto to formou novΘho soketu pro p°ipojenφ
klienta a naslouchacφ p°ipojenφ z∙stßvß otev°eno pro akceptovßnφ ostatnφch
klientsk²ch po╛adavk∙.
SeverovΘ p°ipojenφ
ServerovΘ p°ipojenφ je formovßno serverov²mi sokety, kdy╛
naslouchacφ soket akceptuje klientsk² po╛adavek. Popis serverovΘho soketu,
kter² kompletuje p°ipojenφ ke klientu je zaslßn klientu, kdy╛ server p°ipojenφ
akceptuje. P°ipojenφ je z°φzeno, kdy╛ klientsk² soket p°ijme tento popis
a kompletuje p°ipojenφ.
Popisovßnφ soket∙
Sokety umo╛≥ujφ na╣i sφ╗ovΘ aplikaci komunikovat s ostatnφmi
systΘmy v sφti. Na ka╛d² soket se m∙╛eme dφvat jako na koncov² bod sφ╗ovΘho
propojenφ. Mß adresu, kterß specifikuje:
-
systΘm na kterΘm je spu╣t∞n
-
typ rozhranφ, kterΘmu rozumφ
-
port pou╛it² pro p°ipojenφ
Pln² popis soketovΘho propojenφ, musφ poskytnout adresy soket∙
na obou koncφch p°ipojenφ. M∙╛eme popsat adresu ka╛dΘho soketovΘho koncovΘho
bodu p°edßnφm
IP adresy nebo jmΘna hostitele
a Φφsla portu.
D°φve ne╛ m∙╛eme z°φdit propojenφ soket∙, musφme pln∞
popsat sokety tvo°φcφ jeho koncovΘ body. N∞kterΘ informace jsou dostupnΘ
ze systΘmu, na kterΘm je na╣e aplikace spu╣t∞na. Nap°. nemusφme zadßvat
lokßlnφ IP adresu klientskΘho soketu nebo╗ tato informace je zjistitelnß
z operaΦnφho systΘmu.
Informace, kterΘ musφme poskytnout zßvisφ na typu soketu
se kter²m pracujeme. Klientsk² soket musφ popsat server, ke kterΘmu se
chceme p°ipojit. Naslouchacφ soket serveru musφ popsat port, kter² reprezentuje
poskytovanou slu╛bu.
Popisovßnφ hostitele
Hostitel je systΘm, spou╣t∞jφcφ aplikaci, kterß obsahuje
soket. Hostitele pro soket m∙╛eme popsat jeho IP adresou, co╛ je °et∞zec
Φty° Φφseln²ch hodnot (slabik) v teΦkovΘm zßpisu Internetu, jako je
123.197.1.2
Jeden systΘm m∙╛e b²t identifikovßn vφce ne╛ jednou IP
adresou.
IP adresy jsou obtφ╛n∞ zapamatovatelnΘ a jsou zdrojem
chyb. Alternativou je pou╛itφ jmΘna hostitele. JmΘno hostitele je p°ezdφvka
pro IP adresu, kterou Φasto vidφme v URL (Uniform Resource Locators). Je
to °et∞zec obsahujφcφ jmΘno domΘny a slu╛by, nap°.
http://www.wSite.Com
V Internetu poskytujeme jmΘno hostitele pro IP adresu
systΘmu na Internetu. Na poΦφtaΦφch s operaΦnφm systΘmem Windows 95/98/NT,
pokud jmΘno hostitele nenφ dostupnΘ, pak jej m∙╛eme vytvo°it pro na╣i lokßlnφ
adresu zadßnφm jmΘna do souboru HOSTS. Vφce informacφ o souboru HOSTS nalezneme
v dokumentaci Soket∙ Windows.
ServerovΘ sokety nepot°ebujφ specifikovat hostitele.
Lokßlnφ IP adresa m∙╛e b²t p°eΦtena ze systΘmu. Pokud systΘm mß vφce ne╛
jednu IP adresu, pak serverovΘ sokety naslouchajφcφ klientsk²m po╛adavk∙m
naslouchajφ na v╣ech IP adresßch souΦasn∞. Kdy╛ serverov² soket akceptuje
p°ipojenφ, pak klientsk² soket poskytne vzdßlenou IP adresu. Klientsk²
soket musφ specifikovat vzdßlenΘho hostitele poskytnutφm jmΘna hostitele
nebo IP adresy.
V∞t╣ina aplikacφ pou╛φvß jmΘno hostitele pro specifikaci
systΘmu. JmΘno hostitele je snadn∞ji zapamatovatelnΘ a snadn∞ji se testuje
na typografickΘ chyby. Dßle server m∙╛e zm∞nit systΘm nebo IP adresu, kterß
je p°i°azena k jistΘmu jmΘnu hostitele. Pou╛itφm jmΘna hostitele m∙╛e klientsk²
soket nalΘzt abstraktnφ mφsto reprezentovanΘ jmΘnem hostitele i kdy╛ jeho
IP adresa se zm∞nφ.
Pokud jmΘno hostitele je neznßmΘ, pak klientsk² soket
musφ specifikovat systΘm serveru pomocφ jeho IP adresy. Specifikace serverovΘho
systΘmu pomocφ IP adresy je rychlej╣φ. Kdy╛ poskytneme jmΘno hostitele,
pak soket musφ hledat IP adresu p°i°azenou k tomuto jmΘnu hostitele, d°φve
ne╛ m∙╛e lokalizovat systΘm serveru.
Pou╛φvßnφ port∙
I kdy╛ IP adresa poskytuje dostatek informacφ k nalezenφ
systΘmu na druhΘm konci soketovΘho p°ipojenφ, musφme takΘ zadat Φφslo portu
na tomto systΘmu. Bez Φφsel port∙ by systΘm mohl pracovat pouze s jednφm
p°ipojenφm. ╚φsla port∙ jsou jednoznaΦnΘ identifikßtory, kterΘ umo╛≥ujφ
jednomu systΘmu hostit souΦasn∞ vφce p°ipojenφ, p°i°azenφm ka╛dΘmu p°ipojenφ
samostatnΘho Φφsla portu.
Z jednoho pohledu, Φφsla port∙ jsou ΦφselnΘ k≤dy pro
slu╛by implementovanΘ sφ╗ovou aplikacφ. To je konvence, kterß umo╛≥uje
naslouchacφm serverov²m p°ipojenφm b²t dostupn²mi na pevn²ch Φφslech port∙
a tedy mohou b²t hledßny klientsk²mi sokety. ServerovΘ sokety naslouchajφ
na portu Φφsla p°i°azenΘho ke slu╛b∞, kterou poskytuje. Kdy╛ akceptujφ
p°ipojenφ na klientsk² soket, pak vytvß°φ samostatnΘ soketovΘ p°ipojenφ,
kterΘ pou╛φvß jinΘ Φφslo portu. Tφmto zp∙sobem naslouchacφ p°ipojenφ m∙╛e
stßle poslouchat na portu Φφsla p°i°azenΘho ke slu╛b∞.
KlientskΘ sokety pou╛φvajφ volnß lokßlnφ Φφsla port∙,
kterß nejsou pou╛φvßny ostatnφmi sokety. Specifikujφ Φφslo portu serverovΘho
soketu, ke kterΘmu se cht∞jφ p°ipojit a tak nalΘzt serverovou aplikaci.
╚asto toto Φφslo portu je specifikovßno nep°φmo, jmΘnem po╛adovanΘ slu╛by.
Pou╛φvßnφ komponent soket∙
C++ Builder poskytuje (na strßnce Internet Palety
komponent) dv∞ komponenty soket∙, klientsk²
soket a serverov² soket,
kterΘ umo╛≥ujφ na╣im sφ╗ov²m aplikacφm p°ipojenφ na jin² poΦφtaΦ a kterΘ
umo╛≥ujφ Φφst a zapisovat informace pomocφ tohoto propojenφ. Ke ka╛dΘ z
t∞chto komponent je p°i°azen objekt soketu Windows, kter² reprezentuje
koncov² bod aktußlnφho propojenφ soket∙. Komponenta soketu pou╛φvß objekty
soket∙ Windows k zaobalenφ volßnφ API soketu Windows a tak na╣e aplikace
se nemusφ zab²vat detaily z°izovßnφ p°ipojenφ nebo sprßvou zprßv soketu.
Pokud chceme pracovat s volßnφm API soketu Windows nebo
p°izp∙sobit detaily propojenφ, pak m∙╛eme pou╛φt vlastnosti, udßlosti a
metody objektu soketu Windows.
Pou╛φvßnφ klientsk²ch soket∙
P°idßnφm komponenty klientskΘho soketu (TClientSocket)
na nß╣ formulß° nebo datov² modul zapojφme na╣i aplikaci do klienta TCP/IP.
KlientskΘ sokety umo╛≥ujφ specifikovat serverov² soket, ke kterΘmu se chceme
p°ipojit a slu╛bu, kterou po╛adujeme od serveru. Kdy╛ ji╛ mßme popsanΘ
po╛adovanΘ p°ipojenφ, pak m∙╛eme pou╛φt komponentu soketu klienta ke kompletovßnφ
p°ipojenφ na server.
Ka╛dß komponenta klientskΘho soketu pou╛φvß jeden objekt
soketu Windows (TClientWinSocket) k reprezentaci klientskΘho koncovΘho
bodu v p°ipojenφ.
KlientskΘ sokety pou╛φvßme ke:
Specifikace ╛ßdanΘho serveru
Komponenta klientskΘho soketu mß °adu vlastnostφ, kterΘ umo╛≥ujφ
specifikovat systΘm serveru a port, ke kterΘmu se chceme p°ipojit. SystΘm
serveru m∙╛eme specifikovat jeho jmΘnem hostitele pomocφ vlastnosti Host.
Pokud neznßme jmΘno hostitele, nebo pokud chceme urychlit lokalizaci serveru,
pak m∙╛eme specifikovat teΦkovou IP adresu systΘmu serveru pomocφ vlastnosti
Address.
Musφme specifikovat jmΘno hostitele nebo IP adresu. Pokud specifikujeme
obojφ, pak komponenta pou╛ije jmΘno hostitele.
Mimo systΘmu serveru, musφme specifikovat port na systΘmu
serveru, ke kterΘmu se nß╣ klientsk² soket chce p°ipojit. M∙╛eme chtφt
specifikovat Φφslo portu serveru p°φmo pomocφ vlastnosti Port nebo
nep°φmo pojmenovßnφm po╛adovanΘ slu╛by pomocφ vlastnosti Service.
Pokud specifikujeme obojφ, pak je pou╛ito jmΘno slu╛by.
Formovßnφ p°ipojenφ
Pokud ji╛ mßme nastaveny vlastnosti komponenty klientskΘho
soketu na popis serveru ke kterΘmu se chceme p°ipojit, pak se m∙╛eme za
b∞hu p°ipojit volßnφm metody Open. Pokud chceme aby na╣e aplikace
se p°ipojovala automaticky p°i spu╣t∞nφ, pak nastavφme vlastnost Active
p°i nßvrhu pomocφ Inspektora objekt∙ na true.
Zφskßvßnφ informacφ o p°ipojenφ
Po zkompletovßnφ p°ipojenφ na soket serveru, m∙╛eme pou╛φt
objekt klientskΘho soketu Windows p°i°azen² k na╣φ komponent∞ klientskΘho
soketu k zφskßnφ informacφ o p°ipojenφ. Pomocφ vlastnosti Socket
zφskßme p°φstup k objektu klientskΘho soketu Windows. Tento objekt soketu
Windows mß vlastnosti, kterΘ umo╛≥ujφ urΦit adresu a Φφslo portu pou╛itΘ
klientsk²m a serverov²m soketem na koncφch p°ipojenφ. Vlastnost SocketHandle
m∙╛eme pou╛φt k zφskßnφ madla soketu p°ipojenφ pro pou╛itφ ve volßnφch
API soketu Windows. Vlastnost Handle m∙╛eme pou╛φt k p°φstupu k
oknu zφskßvajφcφmu zprßvy od soketu p°ipojenφ. Vlastnost AsyncStyles
urΦuje jak² typ zprßv toto madlo okna p°ijφmß.
Uzav°enφ p°ipojenφ
Po dokonΦenφ komunikace se serverovou aplikacφ pomocφ soketovΘho
propojenφ, m∙╛eme zru╣it p°ipojenφ volßnφm metody Close. P°ipojenφ
m∙╛e b²t takΘ ukonΦeno serverem. V tomto p°φpad∞ zφskßme oznßmenφ v udßlosti
OnDisconnect.
Pou╛φvßnφ serverov²ch soket∙
P°idßnφm komponenty soketu serveru (TServerSocket)
na nß╣ formulß° nebo datov² modul zapojφme na╣i aplikaci do serveru TCP/IP.
Soket serveru umo╛≥uje specifikovat slu╛bu, kterou poskytujeme nebo port,
kter² chceme pou╛φt k poslouchßnφ klientsk²ch po╛adavk∙. Soket serveru
m∙╛eme pou╛φt k naslouchßnφ a akceptovßnφ po╛adavk∙ klient∙ na p°ipojenφ.
Ka╛dß komponenta soketu serveru pou╛φvß jeden objekt
soketu serveru Windows (TServerWinSocket) k reprezentaci serverovΘho
koncovΘho bodu v naslouchacφm p°ipojenφ. TakΘ pou╛φvß objekt soketu serverovΘho
klienta Windows (TServerClientWinSocket) pro serverov² konec ka╛dΘho
aktivnφho p°ipojenφ na klientsk² soket, kter² server akceptuje.
ServerovΘ sokety pou╛ijeme ke:
Specifikovßnφ po╛adovanΘho
portu
D°φve ne╛ nß╣ serverov² soket m∙╛e naslouchat klientsk²m
po╛adavk∙m, musφme specifikovat port na kterΘm nß╣ server bude naslouchat.
Tento port m∙╛eme specifikovat pomocφ vlastnosti Port. Pokud na╣e
serverovß aplikace poskytuje standardnφ slu╛bu, kterß je p°i°azena konvencφ
ke specifickΘmu Φφslu portu, pak m∙╛eme port specifikovat nep°φmo pomocφ
vlastnosti Service. P°i nastavovßnφ Φφsla portu je vhodnΘ pou╛φvat
vlastnost Service. Pokud specifikujeme vlastnost Port i Service,
pak soket serveru pou╛ije jmΘno slu╛by.
Naslouchßnφ klientsk²m
po╛adavk∙m
Kdy╛ ji╛ mßme nastaveno Φφslo portu, pak m∙╛eme zaΦφt naslouchat
p°ipojenφm, volßnφm metody Open. Pokud chceme, aby na╣e aplikace
automaticky zaΦala naslouchat p°i spu╣t∞nφ, pak nastavφme vlastnost Active
na
true p°i nßvrhu pomocφ Inspektora objekt∙.
P°ipojovßnφ na klienty
Naslouchßnφ komponentou soketu serveru automaticky akceptuje
po╛adavek klienta na p°ipojenφ, kdy╛ je p°ijat. V²skyt tΘto udßlosti je
oznßmen udßlostφ
OnClientConnect.
Zφskßvßnφ informacφ o p°ipojenφch
Kdy╛ ji╛ mßme otev°eno naslouchacφ p°ipojenφ na╣im serverov²m
soketem, pak m∙╛eme pou╛φt objekt serverovΘho soketu Windows p°i°azen²
k na╣φ komponent∞ serverovΘho soketu k zφskßnφ informacφ o p°ipojenφ. Pou╛ijeme
vlastnost
Socket k zφskßnφ p°φstupu k objektu serverovΘho soketu
Windows. Tento objekt soketu Windows mß vlastnosti, kterΘ umo╛≥ujφ nalΘzt
v╣echny aktivnφ p°ipojenφ klientsk²ch soket∙, kterΘ byly akceptovßny komponentou
serverovΘho soketu. Vlastnost SocketHandle pou╛ijeme k zφskßnφ madla
soketu p°ipojenφ pro pou╛itφ ve volßnφ API soketu Windows. Vlastnost Handle
pou╛ijeme pro p°φstup k oknu, kterΘ p°ijφmß zprßvy od soketu p°ipojenφ.
Ka╛dΘ aktivnφ propojenφ s klientskou aplikacφ je zaobaleno
objektem soketu serverovΘho klienta Windows (TServerClientWinSocket).
M∙╛eme k n∞mu p°istupovat prost°ednictvφm vlastnosti Connections
objektu soketu Windows. Tyto objekty soket∙ serverovΘho klienta Windows
majφ vlastnosti, kterΘ umo╛≥ujφ urΦit adresu a Φφslo portu pou╛itou sokety
serveru a klienta tvo°φcφch koncovΘ body propojenφ. Vlastnost SocketHandle
pou╛ijeme k zφskßnφ madla soketu p°ipojenφ pro pou╛itφ ve volßnφ API soketu
Windows. Vlastnost Handle pou╛ijeme pro p°φstup k oknu, kterΘ p°ijφmß
zprßvy od soketu p°ipojenφ. Vlastnost AsyncStyles urΦuje jakΘ typy
zprßv okno m∙╛e p°ijφmat.
Uzavφrßnφ serverov²ch p°ipojenφ
Kdy╛ chceme ukonΦit naslouchacφ p°ipojenφ, pak volßme metodu
Close.
Tφm ukonΦφme v╣echna otev°enß propojenφ klientsk²ch aplikacφ, zru╣φme nevy°φzenΘ
p°ipojenφ, kterΘ nejsou akceptovßny a ukonΦφme naslouchacφ p°ipojenφ a
tak ji╛ na╣e komponenta serverovΘho soketu nem∙╛e akceptovat ╛ßdnß novß
p°ipojenφ.
Kdy╛ klienti ukonΦφ jednotlivß p°ipojenφ, pak nß╣ serverov²
soket je informovßn udßlostφ OnClientDisconnect.
Reagovßnφ na udßlosti soketu
Kdy╛ zapisujeme aplikaci pou╛φvajφcφ sokety, pak v∞t╣inu
prßce obvykle umis╗ujeme do obsluh udßlostφ komponent soket∙. Udßlosti
OnRead
a OnWrite v neblokujφcφch klientsk²ch soketech nastanou, kdy╛ prob∞hlo
Φtenφ nebo zßpis pomocφ propojenφ soket∙. Podobn∞ serverovΘ sokety (blokujφcφ
nebo neblokujφcφ) zφskßvajφ udßlost OnClientRead a
OnClientWrite.
KlientskΘ sokety zφskßvajφ udßlost OnDisconnect
kdy╛ server ukonΦφ p°ipojenφ a serverovΘ sokety zφskßvajφ udßlost OnClientDisconnect,
kdy╛ klient ukonΦφ p°ipojenφ.
Dßle klientskΘ i serverovΘ sokety generujφ udßlost
chyby, kdy╛ p°ijmou chybovou zprßvu od p°ipojenφ. Komponenty soket∙
takΘ p°ijφmajφ n∞kolik udßlostφ v p°φpad∞ otev°enφ a kompletovßnφ p°ipojenφ.
Pokud na╣e aplikace chce ovliv≥ovat zp∙sob zpracovßnφ otevφranφ soket∙
nebo zahajovßnφ Φtenφ nebo zßpisu, pak m∙╛eme po╛adovat zapsat obsluhy
udßlostφ reagujφcφ na tyto klientskΘ nebo
serverovΘ
udßlosti.
Udßlosti chyb
KlientskΘ sokety generujφ udßlost OnError, kdy╛ p°ijmou
chybovou zprßvu od p°ipojenφ. ServerovΘ sokety generujφ OnClientError.
M∙╛eme zapsat obsluhy t∞chto udßlostφ k reagovßnφ na tyto chybovΘ zprßvy.
Obsluze je p°edßna informace o tom:
-
Kter² objekt soketu Windows p°ijal oznßmenφ chyby.
-
Co soket d∞lal v okam╛iku v²skytu chyby.
-
Chybov² k≤d poskytnut² chybovou zprßvou.
V obsluze m∙╛eme chybu zpracovat a zm∞nit chybov² k≤d na
0 pro zabrßn∞nφ soketu v generovßnφ v²jimky.
Udßlosti klienta
Kdy╛ klientsk² soket otevφrß p°ipojenφ, pak nastanou nßsledujφcφ
udßlosti:
-
Udßlost OnLookup nastane p°ed pokusem lokalizovat
serverov² soket. Od tohoto okam╛iku nem∙╛eme m∞nit vlastnosti Host,
Address,
Port
nebo Service pro zm∞nu lokalizovanΘho serverovΘho soketu. M∙╛eme
pou╛φt vlastnost Socket pro p°φstup k objektu klientskΘho soketu
Windows a vlastnost SocketHandle k provedenφ volßnφ API Windows,
kterΘ ovlivnφ vlastnosti soketu. Nap°. pokud chceme, pak m∙╛eme nastavit
Φφslo portu klientskΘ aplikace (musφme to ud∞lat nynφ).
-
Soket Windows je nastaven a inicializovßn pro oznamovßnφ
udßlostφ.
-
Udßlost OnConnecting nastane po lokalizaci serverovΘho
soketu. Objekt soketu Windows je dostupn² pomocφ vlastnosti Socket
a m∙╛e poskytnout informace o serverovΘm soketu, kter² je na druhΘm konci
propojenφ. Toto je prvnφ mo╛nost zφskßnφ aktußlnφho portu a IP adresy pou╛itΘ
pro propojenφ, kterΘ se mohou li╣it od portu a IP adresy naslouchacφho
soketu, kter² akceptuje p°ipojenφ.
-
Po╛adavek na p°ipojenφ je akceptovßn serverem a kompletovßn
klientsk²m soketem.
-
Po z°φzenφ p°ipojenφ vznikß udßlost OnConnect. Pokud
nß╣ soket mß bezprost°edn∞ zaΦφt Φφst nebo zapisovat data pomocφ propojenφ,
pak to provßdφme v obsluze udßlosti OnConnect.
Udßlosti serveru
Komponenty serverovΘho soketu majφ dva typy p°ipojenφ: naslouchacφ
p°ipojenφ a p°ipojenφ ke klientskΘ aplikaci. ServerovΘ sokety p°ijφmajφ
udßlosti v pr∙b∞hu formovßnφ obou t∞chto p°ipojenφ.
T∞sn∞ p°ed zformovßnφm naslouchacφho p°ipojenφ vznikß
udßlost OnListen. V tomto okam╛iku m∙╛eme zφskat objekt serverovΘho
soketu Windows prost°ednictvφm vlastnosti Socket. M∙╛eme pou╛φt
vlastnost SocketHandle k provedenφ zm∞n na soketu d°φve ne╛ je otev°en
pro naslouchßnφ. Nap°. m∙╛eme chtφt omezit IP adresy serveru pou╛itΘ pro
naslouchßnφ a provedeme to v obsluze udßlosti OnListen.
Kdy╛ serverov² soket akceptuje po╛adavek klientskΘho
p°ipojenφ, pak vzniknou nßsledujφcφ udßlosti:
-
Serverov² soket generuje udßlost OnGetSocket, p°edßnφm
madla soketu Windows pro soket, kter² tvo°φ koncov² bod serverovΘho p°ipojenφ.
Pokud chceme poskytnout svΘho vlastnφho p°izp∙sobenΘho potomka TServerClientWinSocket,
pak jej m∙╛eme vytvo°it v obsluze udßlosti OnGetSocket a tak bude
pou╛it mφsto TServerClientWinSocket.
-
Nastßvß udßlost OnAccept, p°edßvajφcφ nov² objekt
TServerClientWinSocket
obsluze udßlosti. To je prvnφ okam╛ik, kdy m∙╛eme pou╛φt vlastnost TServerClienWinSocket
k zφskßvßnφ informacφ o koncovΘm bodu serveru p°ipojenφ na klienta.
-
Pokud p°i vzniku udßlosti OnGetThread ServerType
je stThreadBlocking, pak chceme poskytnout svΘho vlastnφho p°izp∙sobenΘho
potomka TServerClientThread, tak jej m∙╛eme vytvo°it v obsluze udßlosti
OnGetThread
a bude pou╛φvßn namφsto TServerClientThread.
-
Pokud ServerType je stThreadBlocking, pak nastane
udßlost
OnThreadStart, kdy╛ vlßkno zahßjφ provßd∞nφ. Jestli╛e chceme
provΘst n∞jakou inicializaci vlßkna nebo provΘst n∞jakΘ volßnφ API soketu
Windows p°ed zahßjenφm Φtenφ nebo zßpisu vlßkna v propojenφm, pak pou╛ijeme
obsluhu udßlosti OnThreadStart.
-
Klient kompletuje p°ipojenφ a vznikß udßlost OnClientConnect.
S neblokujφcφm serverem m∙╛eme v tento okam╛ik zahßjit Φtenφ nebo zßpis
v soketovΘm p°ipojenφ.
╚tenφ a zßpis v soketovΘm
propojenφ
D∙vod formovßnφ soketovΘho propojenφ na jin² poΦφtaΦ je to,
╛e m∙╛eme Φφst nebo zapisovat informace v tomto propojenφ. JakΘ informace
Φteme nebo zapisujeme nebo kdy╛ jsou Φteny nebo zapisovßny, zßvisφ na slu╛bßch
p°i°azen²ch k soketovΘmu propojenφ.
╚tenφ a zßpis prost°ednictvφm soket∙ m∙╛e probφhat asynchronn∞,
a tak neblokujeme provßd∞nφ jinΘho k≤du v na╣φ sφ╗ovΘ aplikaci. Toto propojenφ
se naz²vß neblokujφcφ propojenφ.
M∙╛eme takΘ formovat blokujφcφ propojenφ,
kde na╣e aplikace Φekß na dokonΦenφ Φtenφ nebo zßpisu p°ed provedenφm nßsledujφcφho
°ßdku k≤du.
Neblokujφcφ propojenφ
Neblokujφcφ propojenφ Φte a zapisuje asynchronn∞, a tak p°enß╣enß
data neblokujφ provßd∞nφ jinΘho k≤du na╣φ sφ╗ovΘ aplikace. K vytvo°enφ
neblokujφcφho propojenφ:
-
Na klientskΘm soketu nastavφme vlastnost ClientType
na ctNonBlocking.
-
Na serverovΘm soketu nastavφme vlastnost ServerType
na stNonBlocking.
Kdy╛ propojenφ je neblokujφcφ, pak Φtecφ
a zßpisovΘ udßlosti informujφ nß╣ soket, kdy╛ soket na druhΘm konci
propojenφ Φte nebo zapφ╣e informaci.
╚tecφ a zßpisovΘ udßlosti
Neblokujφcφ sokety generujφ Φtecφ a zßpisovΘ udßlosti, kterΘ
informujφ nß╣ soket, kdy╛ je zapot°ebφ Φφst nebo zapisovat v propojenφ.
V klientsk²ch soketech, m∙╛eme reagovat na tyto oznßmenφ v obsluhßch udßlostφ
OnRead
nebo OnWrite. V serverov²ch soketech, m∙╛eme reagovat na tyto udßlosti
v obsluhßch udßlostφ OnClientRead nebo OnClienWrite.
Objekt soketu Windows p°i°azen² k soketovΘmu propojenφ
je poskytnut jako parametr obsluhßm Φtecφch nebo zßpisov²ch udßlostφ. Tento
objekt soketu Windows poskytuje °adu metod umo╛≥ujφcφch Φtenφ nebo zßpis
v propojenφ. Ke Φtenφ ze soketovΘho propojenφ, pou╛φvßme metody ReceiveBuf
nebo
ReceiveText. P°ed pou╛itφm metody ReceiveBuf, pou╛ijeme
metodu
TReceiveLength k zφskßnφ poΦtu slabik, kterΘ soket na druhΘm
konci propojenφ odeslal.
K zßpisu na soketovΘ propojenφ, pou╛φvßme metody SendBuf,
SendStream
nebo SendText. Pokud po zßpisu informacφ na soket ji╛ dßle soketovΘ
propojenφ nepot°ebujeme, pak m∙╛eme pou╛φt metodu SendStreamThenDrop.
Tato metoda uzavφrß soketovΘ p°ipojenφ po zßpisu v╣ech informacφ, kterΘ
mohou b²t p°eΦteny z proudu. Pokud pou╛ijeme metodu SendStream nebo
SendStreamThenDrop,
pak objekt proudu nenφ uvoln∞n. Soket uvolnφ proud automaticky, kdy╛ propojenφ
je uzav°eno.
Poznßmka: SendStreamThenDrop uzavφrß
serverovΘ p°ipojenφ na jistΘho klienta a ne naslouchacφ p°ipojenφ.
Blokujφcφ propojenφ
Kdy╛ propojenφ je blokujφcφ, pak nß╣ soket musφ inicializovat
Φtenφ nebo zßpis v propojenφ namφsto pasivnφho Φekßnφ na oznßmenφ od soketovΘho
propojenφ. Blokujφcφ sokety pou╛ijeme kdy╛ nß╣ konec propojenφ mß na starosti
provßd∞nφ Φtenφ a zßpisu.
Pro klientskΘ sokety, nastavφme vlastnost ClientType
na ctBlocking k formovßnφ blokujφcφho propojenφ. V zßvislosti na
tom co na╣e aplikace provßdφ, m∙╛eme chtφt vytvo°it novΘ b∞╛φcφ vlßkno
pro Φtenφ nebo zßpis, aby na╣e aplikace mohla pokraΦovat v provßd∞nφ k≤du
v jinΘm vlßknu, zatφmco Φekßme na dokonΦenφ Φtenφ nebo zßpisu.
Pro serverovΘ sokety, nastavφme vlastnost ServerType
na stThreadBlocking pro formovßnφ blokujφcφho propojenφ. Proto╛e
blokujφcφ propojenφ pozdr╛uje provßd∞nφ v╣eho ostatnφho k≤du b∞hem Φekßnφ
soketu na Φtenφ nebo zßpis, komponenty serverov²ch soket∙ v╛dy plodφ novΘ
vlßkno pro ka╛dΘ klientskΘ propojenφ, kdy╛ ServerType je stThreadBlocking.
V∞t╣ina aplikacφ, kterΘ pou╛φvajφ blokujφcφ p°ipojenφ
jsou zapsßny na pou╛itφ
vlßken.
Pokud nepou╛φvßme vlßkna, pak m∙╛eme Φφst nebo zapisovat
pomocφ
TWinSocketStream.
Pou╛φvßnφ vlßken
s blokujφcφmi p°ipojenφmi
KlientskΘ sokety automaticky neplodφ novΘ vlßkno, kdy╛ Φteme
nebo zapisujeme pomocφ blokujφcφho p°ipojenφ. Pokud na╣e klientskß aplikace
nic ned∞lß dokud informace nenφ p°eΦtena nebo zapsßna, pak je to vyhovujφcφ.
Jestli╛e na╣e aplikace obsahuje u╛ivatelskΘ rozhranφ, kterΘ musφ stßle
reagovat na u╛ivatele, pak pro Φtenφ a zßpis musφme po╛adovat samostatnΘ
vlßkno.
Kdy╛ serverov² soket formuje blokujφcφ p°ipojenφ, pak
v╛dy plodφ samostatnΘ vlßkno pro ka╛dΘ klientskΘ p°ipojenφ a tak klient
nemusφ Φekat a╛ jin² klient dokonΦφ Φtenφ nebo zßpis ve svΘm p°ipojenφ.
Implicitn∞ serverov² soket pou╛φvß objekt TServerClientThread k
implementaci b∞╛φcφho vlßkna pro ka╛dΘ p°ipojenφ.
Objekt TServerClientThread simuluje udßlosti OnClientRead
a OnClientWrite, kterΘ vynikajφ p°i neblokujφcφm p°ipojenφ. NicmΘn∞,
tyto udßlosti vznikajφ i na naslouchacφm soketu, kter² nenφ vlßknov∞ lokßlnφ.
Pokud klientskΘ po╛adavky jsou ΦastΘ, pak m∙╛eme chtφt vytvo°it svΘho vlastnφho
potomka TServerClientThread k poskytnutφ vlßknov∞ bezpeΦnΘho Φtenφ
a zßpisu.
Kdy╛ zapisujeme klientskß
vlßkna nebo zapisujeme serverovß
vlßkna, pak musφme pou╛φt TWinSocketStream
k provßd∞nφ aktußlnφho Φtenφ a zßpisu.
Pou╛φvßnφ TWinSocketStream
Kdy╛ implementujeme vlßkno pro blokujφcφ p°ipojenφ, pak musφme
urΦit, zda soket na druhΘm konci propojenφ je urΦen pro Φtenφ nebo pro
zßpis. Blokujφcφ p°ipojenφ neoznamujφ soketu Φas Φtenφ nebo zßpisu. Abychom
je vid∞li, kdy╛ p°ipojenφ je reßlnΘ, pou╛ijeme objekt TWinSocketStream.
TWinSocketStream
poskytuje metody pomßhajφcφ koordinovat Φasy Φtenφ a zßpisu. Volßnφm metody
WaitForData
Φekßme, dokud soket na druhΘm konci p°ipojenφ neprovede zßpis.
Kdy╛ Φtenφ nebo zßpis pou╛φvß TWinSocketStream,
pak Φas proudu je p°ekroΦen, pokud Φtenφ nebo zßpis nenφ dokonΦeno ve specifikovanΘm
ΦasovΘm intervalu. V²sledkem tohoto p°ekroΦenφ Φasu je ukonΦenφ Φtenφ nebo
zßpisu a zru╣enφ p°ipojenφ.
Poznßmka: TWinSocketStream nem∙╛eme
pou╛φt pro neblokujφcφ p°ipojenφ.
Zßpis klientsk²ch vlßken
K zßpisu vlßkna pro klientskΘ p°ipojenφ, definujeme nov²
objekt vlßkna pomocφ dialogovΘho okna New Thread Object. Metoda
Execute
na╣eho novΘho objektu vlßkna zpracovßvß detaily Φtenφ a zßpisu vlßknovΘho
p°ipojenφ. Je vytvo°en objekt TWinSocketStream a je pou╛φvßn ke
Φtenφ nebo zßpisu. Nap°.
void __fastcall TMyClientThread::Execute()
{
// vytvo°enφ TWinSocketStream pro
Φtenφ a zßpis
TWinSocketStream *pStream=new TWinSocketStream(ClientSocket1->Socket,
60000);
try
{
//zφskßnφ a zpracovßvßnφ
p°φkazu dokud p°ipojenφ nebo vlßkno nenφ ukonΦeno
while (!Terminated &&
ClientSocket1->Active)
{
try
{
char buffer[10];
GetNextRequest(buffer); // GetNextRequest musφ b²t vlßknov∞ bezpeΦnß metoda
// zßpis po╛adavku na server
pStream->Write(buffer, strlen(buffer) + 1);
// pokraΦovßnφ v komunikaci (Φtenφ reakce ze serveru)
...
}
catch (Exception
&E)
{
if (!E.ClassNameIs("EAbort"))
Synchronize(HandleThreadException()); // musφme zapsat HandleThreadException
}
}
}
__finally
{
delete pStream;
}
}
K pou╛itφ na╣eho vlßkna, vlßkno vytvo°φme v obsluze udßlosti
OnConnect.
Zßpis serverov²ch vlßken
Vlßkna pro serverovß p°ipojenφ jsou potomci TServerClientThread.
Nem∙╛eme tedy pou╛φt dialogovΘ okno New Thread Object. Musφme je
deklarovat ruΦn∞ takto:
class PACKAGE TMyServerThread : public ScktComp::TServerClientThread
{
public
void __fastcall ClientExecute(void);
}
K implementaci tohoto vlßkna, p°episujeme metodu ClientExecute
(mφsto metody Execute).
Implementovßnφ metody ClientExecute se podobß
zßpisu metody
Execute vlßkna pro klientskΘ p°ipojenφ. Mφsto pou╛itφ
komponenty klientskΘho soketu kterou umφstφme do na╣φ aplikace z Palety
komponent, serverov∞ klientskΘ vlßkno musφ pou╛φt objekt TServerClientWinSocket,
kter² je vytvo°en kdy╛ naslouchacφ soket serveru akceptuje klientskΘ p°ipojenφ.
Je dostupnΘ jako ve°ejnß vlastnost ClientSocket. Dßle m∙╛eme pou╛φt
chrßn∞nou metodu HandleException namφsto zßpisu svΘ vlastnφ vlßknov∞
bezpeΦnΘ obsluhy v²jimky. Nap°.
void __fastcall TMyServerThread::ClientExecute()
{
while (!Terminated && ClientSocket->Connected)
// zji╣t∞nφ ╛e p°ipojenφ je aktivnφ
{
try
{
TWinSocketStream
*pStream = new TWinSocketStream(ClientSocket, 60000);
try
{
char buffer[10];
memset(buffer, 0, sizeof(buffer));
if (pStream->WaitForData(60000)) // Dßme klientu 60 sekund k zahßjenφ zßpisu
{
if (pStream->Read(buffer, sizeof(buffer) == 0)
ClientSocket->Close(); // nenφ-li p°eΦteno v 60 sekundßch, pak uzav°eme
p°ipojenφ
// zpracovßnφ po╛adavku
...
}
else
ClientSocket->Close();
}
__finally
{
delete pStream;
}
}
catch (...)
{
HandleException();
}
}
}
Varovßnφ: Serverov² soket odklßdß pou╛φvanΘ
vlßkno. Musφme si b²t jisti, ╛e metoda ClientExecute provede nezbytnΘ
inicializace jako v²sledek zm∞ny z poslednφho provedenΘho vlßkna.
K pou╛itφ na╣eho vlßkna, vytvo°φme obsluhu udßlosti OnGetThread.
Kdy╛ zapisujeme vlßkno, pak nastavφme parametr CreateSuspended na
false.
-
Podφvejme se na aplikaci Chat, kterß umo╛≥uje "rozmlouvat" dv∞ma
u╛ivatel∙m na r∙zn²ch poΦφtaΦφch. Jednß se op∞t o ji╛ hotovou aplikaci.
M∙╛ete
si ji stßhnout. ProhlΘdn∞te si, jak vyu╛φvß sokety a vyzkou╣ejte ji.