2. diel - Sieť v Jave - Balíky pre sieťovú komunikáciu
V minulej lekcii, Sieť v Jave - Úvod , sme si vysvetlili základné pojmy sieťovej komunikácie v Jave, popísali si jej techniky a zoznámili sa s terminológiou.
Balíky Java pre sieťovú komunikáciu
Medzi základné balíky v Jave pre prácu so sieti môžeme zaradiť:java.net.*
java.io.*
java.nio.*
java.nio.channels.*
Existuje aj balíček java.rmi s pomocou ktorého je možné realizovať klient/server aplikácie bez nutnosti znalosti socketov a písania relatívne zložitého kódu. Pre odtienenie programátorov od zložitej práce a zníženie nákladov na vývoj softvéru boli vytvorené knižnice implementujúce techniku volania procedúr.
Základné balíčky si teraz popíšeme podrobnejšie:
Balíček java.net
Tento balíček je súčasťou java API už od svojej prvej verzie. Poskytuje
podporu pre dva bežné sieťové protokoly TCP a
UDP, ktoré sú vyžadované pre komunikáciu v rámci siete.
Balíček java.net
teda ponúka základnú funkčnosť pre
sieťové aplikácie, pričom ju je možné rozdeliť do dvoch častí:
- High Level API - Zaoberajú sa abstrakciou URI (Universal Resource Identifier), URL (Universal Resource Locator) a Connections, tj pripojenie k zdroju, na ktorý odkazujú URL.
- Nízkoúrovňové API - Zaoberajú sa abstrakciami adries, tj sieťových identifikátorov, Sockets, tj obojsmerného mechanizmu dátovej komunikácie a Interfaces, tj sieťových rozhraní.
Okrem prostriedkov na spojovo orientovanú a datagramovú komunikáciu poskytuje balík taktiež možnosti komunikácie typu multicast, vrátane metód pre pripájanie a odpájanie sa k jednotlivým multicast skupinám.
Triedy URL
a
URLConnection
Trieda URL
v Jave je vstupným bodom ku všetkým dostupným
zdrojom na internete. Adresa URL triedy popisuje Uniform Resource
Locator, čo je signál pre „zdroj“ na World Wide Web. Zdroj
môže označovať jednoduchý súbor alebo adresár, alebo môže označovať
ťažší objekt, ako je dotaz do databázy alebo na vyhľadávač.
Trieda URLConnection
v Jave je abstraktná trieda popisujúca
pripojenie zdroja, ako je definované podobnou URL. Trieda
URLConnection
sa používa na pomoc s dvoma odlišnými, ale
vzájomne prepojenými účelmi. Po prvé poskytuje kontrolu interakcie so
serverom (najmä HTTP serverom) ako triedou URL. Navyše s
URLConnection
môže používateľ overiť hlavičku prenesenú
serverom a môže následne reagovať. Užívateľ môže tiež konfigurovať
polia hlavičky používané v klientskych požiadavkách práve pomocou
URLConnection
.
Socket
a
ServerSocket
Na realizáciu spojenia medzi dvoma aplikáciami sú potrebné dva odlišné
sockety. Prvý čakajúci na prichádzajúce spojenie (serverový) a druhý,
ktorý musí spojenie vytvoriť (klientský).
Na vytvorenie klientskeho socketu (používa sa na komunikáciu klienta)
slúži inštancia triedy Socket
. Prostredníctvom tejto triedy
môžeme čítať a písať správy. Na vytvorenie serverového socketu
(používa sa na strane servera) slúži inštancia triedy
ServerSocket
. Aby sa klientský socket mohol pripojiť, musí sa
konštruktoru triedy Socket
odovzdať adresa a
port cieľa. Adresa môže byť inštanciou triedy
String
alebo inštanciou triedy InetAddress
. Adresa
typu InetAddress
v sebe zapuzdruje IP adresu cieľa. Inštancia
triedy InetAddress
sa získa pomocou statickej metódy
getByName(String host)
triedy InetAddress
. Táto
metóda na vstupe očakáva buď IP alebo URL adresu cieľa.
Programovanie socketu a prácu s triedami URL
a
URLConnection
vrátane použitia triedy InetAddress
si
ukážeme v niektorom z ďalších článkov.
Balíček java.io
Druhý balíček je tiež súčasťou API od prvej verzie. Obsahuje triedy pre
prácu s dátovými prúdmi alebo triedy pre spracovanie
dátových výstupov a vstupov.
V spojení so sieťovou komunikáciou stojí za zmienku iba vstupné
a výstupné prúdy, ktoré je možné pripojiť na zdroj alebo cieľ
dát. Sú to ByteArrayInputStream
resp.
ByteArrayOutputStream
. Ak zabalíme tieto prúdy pomocou
DataInputStream
resp. DataOutputStream
, môžu
poskytovať spôsob, ako prenášať primitívne dátové typy Javy. Ku
všetkým ostatným zdrojom dát je možné získať prístup primitívnymi
implementáciami tried InputStream
resp.
OutputStream
.
Balíček java.nio
Ponúka nové prístupy pre prácu so sieťovými prostriedkami (sockety),
bez nutnosti tvorby vlákien, umožňuje prácu s tzv.
buffermi. Inými slovami balík ponúka pre každý primitívny
dátový typ (okrem boolean
) triedy bufferov – ide o rýchlejšie
riešenie ako sú klasické polia.
Hlavnými prvkami každého bufferu je jeho kapacita, pozícia a medza. Kapacita udáva maximálny počet prvkov, ktoré buffer môže obsahovať. Pozícia je index aktuálneho prvku, ktorý má byť čítaný alebo zapisovaný. Hranica označuje index prvej pozície, ktorú ešte nemožno prečítať, alebo na ktorú nemožno zapísať:
Všetky buffery sú zdedené od spoločnej triedy Buffer
.
Balíček
java.nio.channels
Obsahuje niekoľko kanálov pre prácu so sieťou. Napríklad
kanály pre prácu s datagramami, so socketmi, routy a ďalšie. Kanály
spoločne s buffermi môžu ponúkať totožnú funkčnosť ako triedy
InputStream
a OutputStream
.
Z tohto balíka si predstavíme iba dve triedy:
SocketChannel
- klientsky kanálServerSocketChannel
- serverový kanál
Klientsky kanál
TriedaSocketChannel
v sebe zapuzdruje klientsky socket a jeho
využitie je rovnaké ako inštancia triedy Socket
. Spoločne s
použitím Selektoru
a objektu ServerSocketChannel
umožňujú vytvoriť neblokujúci, bezvláknový server.
Inštanciu triedy SocketChannel
vytvoríme pomocou metódy
open(SocketChannel remote)
- otvoríme kanál socketu a pripojíme
sa na adresu zadanú v parametri remote
. Ak zavoláme
open()
s prázdnym parametrom, musíme neskôr na pripojenie
socketu použiť metódu connect(SocketAddres remote)
objektu
SocketChannel
:
Hlavné metódy | Popis |
---|---|
public static SocketChannel open( SocketAddress remote ) | Vytvorí inštanciu triedy SocketChannel , otvorí kanál
socketu a pripojí sa na adresu zadanú v parametri remote . |
public static SocketChannel connect( SocketAddres remote ) | Pripája socket tohto kanála. Trieda SocketAddress je
rodičovskou triedou. |
public void close() | Uzavrie kanál. |
public int read( ByteBuffer dst ) | Načíta dáta z kanála do bufferu. Vracia počet načítaných
dát. Ak vráti hodnotu -1 , kanál bol uzavretý. |
public int write( ByteBuffer dst ) | Zapisuje dáta z buffera na kanál. Pred akýmkoľvek zápisom bufferu je
potrebné volať metódu flip() , ktorá ohraničí dáta v buffere.
Metóda vracia počet zapísaných dát. |
Serverový kanál
TriedaServerSocketChannel
obsahuje metódu open()
ktorá vracia jej inštanciu. Objekt vytvorený touto metódou ešte nie je
plnohodnotný serverový kanál. Aby bol kanál kompletný a bol schopný
počúvať, je potrebné k nemu pridružiť objekt ServerSocket
získaný metódou socket()
a zavolaním jeho metódy
bind(SocketAddress address, int port)
. Prijatie nového kanála
prichádzajúceho klienta je realizované metódou accept()
triedy
ServerSocektChannel
. Pomocou metódy
configureBlocking(boolean block)
je vhodné nastaviť serverovému
kanálu neblokujúci mód. Voľba módu zásadne ovplyvňuje metódu
accept()
. Ak bude nastavený neblokujúci mód, potom metóda
accept()
vracia buď SocketChannel
klienta alebo
null
a nijako neblokuje beh aplikácie. Pri blokujúcom móde
metóda accept()
blokuje sieťové vlákno dovtedy, kým sa na
server niekto nepripojí. Po ukončení práce so serverom je potrebné
uzavrieť ServerSocket
jeho vlastnou metódou close()
a ServerSocketChannel
taktiež jeho vlastnou metódou
close()
.V budúcej lekcii, Sieť v Jave - Práca s URL , si popíšeme triedu java.net.URL vrátane ich hlavných metód a ukážeme si, ako ich použiť v praxi.