8. diel - Java server - Komunikačný protokol
V minulej lekcii, Java server - Zapisovacia vlákno , sme vylepšili odozvu servera pri zachovaní
jeho funkčnosti. Dnes si navrhneme komunikačný protokol, pomocou ktorého
budú komunikovať klient a server. Doteraz sme posielali textové správy,
avšak nevedomky sme k tomu využívali posielanie kompletného objektu, nie len
textu. Text sme mohli posielať, pretože triedu String
možno
serializovať a poslať po sieti.
Posielanie objektov
Java disponuje možnosťou posielať po sieti celej objekty. Tejto funkcie
využijeme pri implementácii nášho komunikačného protokolu. Pre posielanie
a príjem objektov slúžia triedy
ObjectInputStream
a
ObjectOutputStream
. Všetky objekty, ktoré budeme
posielať, musí obsahovať konštantu serialVersionUID
. Jedná sa
o unikátne číslo, podľa ktorého sa budú objekty znova zostavovať na
druhej strane linky. Obvykle IDE disponuje možnosťou toto číslo
vygenerovať. Ďalej musí všetky tieto objekty implementovať rozhranie
Serializable
. Jedná sa len o značkovacia
rozhranie, takže nevyžaduje implementovať žiadne metódy. Je to informácia
pre JVM, že takéto objekty je možné serializovať a poslať po sieti.
Komunikačný protokol
Všetky triedy, ktoré budeme vytvárať, sa budú nachádzať v module
share
. To preto, aby k nim mal prístup ako modul
client
, tak modul
server
. V module
share
, v priečinku src/main/java/
,
založte balík, ktorý zodpovedá celému projektu, v mojom prípade je to:
cz.stechy.chat
. V tomto balíčku vytvorte balíček
net.message
, v ktorom budeme uchovávať všetky
triedy pre komunikáciu medzi klientom a serverom. V tomto balíčku založíme
rozhranie, ktoré bude reprezentovať samotnú správu
IMessage
. Rozhranie necháme dediť od rozhrania
Serializable
, aby sme nemuseli toto rozhranie
implementovať v konkrétnych triedach a mali istotu, že triedu pôjde odoslať
pomocou ObjectOutputStream
u.
public interface IMessage extends Serializable { String getType(); Object getData(); default boolean isSuccess() { return true; } }
Rozhranie obsahuje tri metódy:
getType()
- vráti typ správy; každý typ bude zodpovedať jednej triedegetData()
- vráti dáta, ktoré správa nesieisSuccess()
- informácie, či ak sa požadovaná akcia vykonala v poriadku, alebo skončila neúspechom
Rovno si vytvoríme jednoduchú implementáciu rozhrania
IMessage
, pomocou ktorej budeme opäť schopní
odosielať textové správy:
public class TextMessage implements IMessage { public static final String MESSAGE_TYPE = "text"; private final String data; public TextMessage(String data) { this.data = data; } @Override public String getType() { return "text"; } @Override public Object getData() { return data; } }
Implementácie protokolu
Keď sme nadefinovali základné triedu, ktorú budeme posielať po sieti, je
potrebné upraviť všetky miesta v kóde, kde odosielame alebo prijímame dáta
typu Object
, na dátový typ
IMessage
.
Rozhranie, kde musíme zmeniť dátový typ, sú:
IClient
void sendMessageAsync(IMessage message);
void sendMessage(IMessage message) throws IOException;
IWriterThread
void sendMessage(ObjectOutputStream writer, IMessage message);
V triede Client
je potreba upraviť prijímanie
správ:
IMessage received;
while ((received = (IMessage) reader.readObject()) != null) {}
Teraz už neprijímame triedu Object
, ale
rozhranie IMessage
. Pretypovanie je tu na mieste,
pretože náš protokol stojí na myšlienke, že všetky objekty, ktoré
pošleme budú mať spoločné rozhranie práve
IMessage
.
V triede ClientDispatcher
musíme upraviť
odosielaní správy, využijeme triedu
TextMessage
:
client.sendMessage(new TextMessage("count: " + count));
Testovanie funkčnosti
Konečne sa pozrieme, či ak naša doterajšia práca bola úspešná a otestujeme, či je server schopný komunikovať s klientom.
V module client
vytvoríme opäť
zodpovedajúce balíček a v ňom triedu
SimpleClient
. Trieda bude mať iba jednu metódu
main()
, v ktorej nadviažeme spojenie so serverom, odošleme dáta,
počkáme, až príde odpoveď a spojenie ukončíme:
public class SimpleClient { public static void main(String[] args) throws Exception { Socket socket = new Socket("localhost", 15378); Thread.sleep(1000); ObjectOutputStream writer = new ObjectOutputStream(socket.getOutputStream()); writer.writeObject(new TextMessage("Hello from client.")); writer.flush(); ObjectInputStream reader = new ObjectInputStream(socket.getInputStream()); System.out.println(((IMessage) reader.readObject()).getData().toString()); socket.close(); } }
Spustite najskôr server a potom klienta. Výsledkom by malo byť vypísanie správy "Hello from client".
To by bolo pre dnešné kratšie lekciu všetko. Nabudúce, v lekcii Java server - Event bus , si naimplementujeme jednoduchú event bus.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 20x (142.93 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java