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ú:
IClientvoid sendMessageAsync(IMessage message);void sendMessage(IMessage message) throws IOException;
IWriterThreadvoid 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é 21x (142.93 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java
