Black Friday Black Friday
Black Friday výprodej! Až 80 % extra bodů zdarma! Více informací zde

Lekce 8 - Java server - Komunikační protokol

Java Server pro klientské aplikace Java server - Komunikační protokol

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Java server - Zapisovací vlákno, jsme vylepšili odezvu serveru při zachování jeho funkčnosti. Dnes si navrhneme komunikační protokol, pomocí kterého budou komunikovat klient a server. Dosud jsme posílali textové zprávy, ovšem nevědomky jsme k tomu využívali posílání kompletního objektu, ne jen textu. Text jsme mohli posílat, protože třídu String lze serializovat a poslat po síti.

Posílání objektů

Java disponuje možností posílat po síti celé objekty. Této funkce využijeme při implementaci našeho komunikačního protokolu. Pro posílání a příjem objektů slouží třídy ObjectInputStream a ObjectOutputStream. Všechny objekty, které budeme posílat, musí obsahovat konstantu serialVersionUID. Jedná se o unikátní číslo, podle kterého se budou objekty znovu sestavovat na druhé straně linky. Obvykle IDE disponuje možností toto číslo vygenerovat. Dále musí všechny tyto objekty implementovat rozhraní Serializable. Jedná se pouze o značkovací rozhraní, takže nevyžaduje implementovat žádné metody. Je to informace pro JVM, že takovéto objekty je možné serializovat a poslat po síti.

Komunikační protokol

Všechny třídy, které budeme vytvářet, se budou nacházet v modulu share. To proto, aby k nim měl přístup jak modul client, tak modul server. V modulu share, ve složce src/main/java/, založte balíček, který odpovídá celému projektu, v mém případě je to: cz.stechy.chat. V tomto balíčku vytvořte balíček net.message, ve kterém budeme uchovávat veškeré třídy pro komunikaci mezi klientem a serverem. V tomto balíčku založíme rozhraní, které bude reprezentovat samotnou zprávu IMessage. Rozhraní necháme dědit od rozhraní Serializable, abychom nemuseli toto rozhraní implementovat v konkrétních třídách a měli jistotu, že třídu půjde odeslat pomocí ObjectOutputStreamu.

public interface IMessage extends Serializable {
    String getType();
    Object getData();

    default boolean isSuccess() {
        return true;
    }
}

Rozhraní obsahuje tři metody:

  • getType() - vrátí typ zprávy; každý typ bude odpovídat jedné třídě
  • getData() - vrátí data, která zpráva nese
  • isSuccess() - informace, zda-li se požadovaná akce vykonala v pořádku, nebo skončila neúspěchem

Rovnou si vytvoříme jednoduchou implementaci rozhraní IMessage, pomocí které budeme opět schopni odesílat textové zprá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;
    }
}

Implementace protokolu

Když jsme nadefinovali základní třídu, kterou budeme posílat po síti, je potřeba upravit všechna místa v kódu, kde odesíláme nebo přijímáme data typu Object, na datový typ IMessage.

Rozhraní, kde musíme změnit datový typ, jsou:

  • IClient
    • void sendMessageAsync(IMessage message);
    • void sendMessage(IMessage message) throws IOException;
  • IWriterThread
    • void sendMessage(ObjectOutputStream writer, IMessage message);

Podle rozhraní upravte i implementace metod v odpovídajících třídách.

V třídě Client je potřeba upravit přijímání zpráv:

IMessage received;
while ((received = (IMessage) reader.readObject()) != null) {}

Nyní již nepřijímáme třídu Object, ale rozhraní IMessage. Přetypování je zde na místě, protože náš protokol stojí na myšlence, že všechny objekty, které pošleme budou mít společné rozhraní právě IMessage.

V třídě ClientDispatcher musíme upravit odesílání zprávy, využijeme třídu TextMessage:

client.sendMessage(new TextMessage("count: " + count));

Testování funkčnosti

Konečně se podíváme, zda-li naše dosavadní práce byla úspěšná a otestujeme, zda-li je server schopný komunikovat s klientem.

V modulu client vytvoříme opět odpovídající balíček a v něm třídu SimpleClient. Třída bude mít pouze jednu metodu main(), ve které navážeme spojení se serverem, odešleme data, počkáme, až přijde odpověď a spojení 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();
    }
}

Spusťte nejdříve server a pak klienta. Výsledkem by mělo být vypsání zprávy "Hello from client".

To by bylo pro dnešní kratší lekci vše. Příště, v lekci Java server - Event bus, si naimplementujeme jednoduchou event bus.


 

Stáhnout

Staženo 3x (129.21 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

 

Článek pro vás napsal Petr Štechmüller
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje primárně programování v Jave, ale nebojí se ani webových technologií.
Miniatura
Předchozí článek
Java server - Zapisovací vlákno
Miniatura
Všechny články v sekci
Server pro klientské aplikace v Javě
Miniatura
Následující článek
Java server - Event bus
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!