Jak vytvořit síťovou aplikaci v Javě (s obrázky)

Obsah:

Jak vytvořit síťovou aplikaci v Javě (s obrázky)
Jak vytvořit síťovou aplikaci v Javě (s obrázky)

Video: Jak vytvořit síťovou aplikaci v Javě (s obrázky)

Video: Jak vytvořit síťovou aplikaci v Javě (s obrázky)
Video: LG Stylo 3: How to Take Screenshot (3 Ways) 2024, Smět
Anonim

Psaní kódu, které se spouští na určitém zařízení, je velmi uspokojivé. Ale psaní kódu, který se spouští na několika zařízeních, která spolu komunikují, je prostě život potvrzující. Tento článek vás naučí, jak se připojit a vyměňovat si zprávy přes síť pomocí protokolu TCP (Control Control Protocol).

V tomto článku nastavíte aplikaci, která k vám připojí počítač a v podstatě z něj udělá blázna - mluvte sami se sebou. Dozvíte se také rozdíl mezi dvěma nejpoužívanějšími streamy pro vytváření sítí v Javě a jejich funkcí.

Datové a objektové toky

Před ponořením do kódu je třeba rozlišit rozdíl mezi dvěma proudy použitými v článku.

Datové toky

Datové toky zpracovávají primitivní datové typy a řetězce. Data odesílaná přes datové toky je třeba ručně serializovat a deserializovat, což ztěžuje přenos složitých dat. Datové toky však mohou komunikovat se servery a klienty napsanými v jiných jazycích než v jazyce Java. Surové toky jsou v tomto aspektu podobné datovým proudům, ale datové toky zajišťují, že jsou data formátována nezávisle na platformě, což je výhodné, protože obě strany budou moci číst odeslaná data.

Streamování objektů

Datové toky objektů zpracovávají primitivní datové typy a objekty, které implementují

Serializovatelné

rozhraní. Data odesílaná přes datové proudy objektů jsou automaticky serializována a deserializována, což usnadňuje přenos složitých dat. Objektové streamy však mohou komunikovat pouze se servery a klienty napsanými v jazyce Java. Taky,

ObjectOutputStream

při inicializaci odešle záhlaví do

InputStream

druhé strany, která při inicializaci blokuje provádění, dokud není přijato záhlaví.

Kroky

Vytvořte síťovou aplikaci v jazyce Java Step1
Vytvořte síťovou aplikaci v jazyce Java Step1

Krok 1. Vytvořte třídu

Vytvořte třídu a pojmenujte ji, jak chcete. V tomto článku bude pojmenován

NetworkAppExample

veřejná třída NetworkAppExample {}

Vytvořte síťovou aplikaci v jazyce Java Step2
Vytvořte síťovou aplikaci v jazyce Java Step2

Krok 2. Vytvořte hlavní metodu

Vytvořte hlavní metodu a deklarujte, že může vyvolat výjimky

Výjimka

typ a jakákoli jeho podtřída - všechny výjimky. To je považováno za špatnou praxi, ale je to přijatelné pro barebone příklady.

public class NetworkAppExample {public static void main (String args) throws Exception {}}

Vytvořte síťovou aplikaci v jazyce Java Step3
Vytvořte síťovou aplikaci v jazyce Java Step3

Krok 3. Deklarujte adresu serveru

Tento příklad bude používat adresu místního hostitele a libovolné číslo portu. Číslo portu musí být v rozsahu od 0 do 65535 (včetně). Čísla portů, kterým je třeba se vyhnout, se však pohybují od 0 do 1023 (včetně), protože jde o vyhrazené systémové porty.

public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; }}

Vytvořte síťovou aplikaci v jazyce Java Step4
Vytvořte síťovou aplikaci v jazyce Java Step4

Krok 4. Vytvořte server

Server je vázán na adresu a port a poslouchá příchozí připojení. V Javě,

ServerSocket

představuje koncový bod na straně serveru a jeho funkcí je přijímání nových připojení.

ServerSocket

nemá streamy pro čtení a odesílání dat, protože nepředstavuje spojení mezi serverem a klientem.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); }}

Vytvořte síťovou aplikaci v jazyce Java Step5
Vytvořte síťovou aplikaci v jazyce Java Step5

Krok 5. Počátek přihlášení serveru

Pro účely protokolování vytiskněte na konzolu, že server byl spuštěn.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); }}

Vytvořte síťovou aplikaci v jazyce Java Step6
Vytvořte síťovou aplikaci v jazyce Java Step6

Krok 6. Vytvořte klienta

Klient je vázán na adresu a port serveru a po navázání připojení poslouchá pakety (zprávy). V Javě,

Zásuvka

představuje buď koncový bod na straně klienta připojený k serveru, nebo připojení (ze serveru) ke klientovi, a slouží ke komunikaci se stranou na druhém konci.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); }}

Vytvořte síťovou aplikaci v jazyce Java Step7
Vytvořte síťovou aplikaci v jazyce Java Step7

Krok 7. Pokus o připojení

Pro účely protokolování vytiskněte na konzole, že došlo k pokusu o připojení.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); }}

Vytvořte síťovou aplikaci v jazyce Java Step8
Vytvořte síťovou aplikaci v jazyce Java Step8

Krok 8. Navažte připojení

Klienti se nikdy nepřipojí, pokud server naslouchá a nepřijímá, jinými slovy navazuje, připojení. V Javě se připojení navazují pomocí

přijmout()

metoda

ServerSocket

třída. Metoda zablokuje provádění, dokud se klient nepřipojí.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); }}

Vytvořte síťovou aplikaci v jazyce Java Step9
Vytvořte síťovou aplikaci v jazyce Java Step9

Krok 9. Zaznamenejte navázané připojení

Pro účely protokolování vytiskněte na konzoli, že bylo navázáno spojení mezi serverem a klientem.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); }}

Vytvořte síťovou aplikaci v jazyce Java Step10
Vytvořte síťovou aplikaci v jazyce Java Step10

Krok 10. Připravte komunikační toky

Komunikace probíhá přes streamy a v této aplikaci je třeba surové toky (připojení z) serveru (ke klientovi) a klientovi zřetězit do datových nebo objektových proudů. Obě strany musí používat stejný typ streamu.

  • Datové toky

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); }}

  • Proudy objektů

    Pokud je použito více proudů objektů, musí být vstupní toky inicializovány ve stejném pořadí jako výstupní toky, protože

    ObjectOutputStream

    odešle hlavičku druhé straně a

    ObjectInputStream

    blokuje provádění, dokud nečte záhlaví.

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); }}

    Pořadí, jak je uvedeno ve výše uvedeném kódu, může být snadněji zapamatovatelné - nejprve inicializujte výstupní toky a poté vstupní toky ve stejném pořadí. Další pořadí pro inicializaci streamů objektů je však následující:

    ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ());

Vytvořte síťovou aplikaci v jazyce Java Step11
Vytvořte síťovou aplikaci v jazyce Java Step11

Krok 11. Zaznamenejte, že komunikace je připravena

Pro účely protokolování vytiskněte na konzoli, že je komunikace připravena.

// kód vynechán import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); // kód vynechán System.out.println ("Komunikace je připravena."); }}

Vytvořte síťovou aplikaci v jazyce Java Step12
Vytvořte síťovou aplikaci v jazyce Java Step12

Krok 12. Vytvořte zprávu

V této aplikaci

Ahoj světe

text bude odeslán na server buď jako

byte

nebo

Tětiva

. Deklarujte proměnnou typu, který závisí na použitém streamu. Použití

byte

pro datové toky a

Tětiva

pro toky objektů.

  • Datové toky

    Pomocí datových proudů se serializace provádí převodem objektů na primitivní datové typy nebo a

    Tětiva

    . V tomto případě,

    Tětiva

    je převeden na

    byte

    místo písemného použití

    writeBytes ()

    metoda, která ukazuje, jak by to bylo provedeno s jinými objekty, jako jsou obrázky nebo jiné soubory.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); System.out.println ("Komunikace je připravena."); byte messageOut = "Hello World".getBytes (); }}

  • Proudy objektů

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); Řetězec messageOut = "Hello World"; }}

Vytvořte síťovou aplikaci v jazyce Java Step13
Vytvořte síťovou aplikaci v jazyce Java Step13

Krok 13. Odešlete zprávu

Zapisujte data do výstupního proudu a vypláchněte stream, abyste se ujistili, že data byla zapsána celá.

  • Datové toky

    Nejprve je třeba odeslat délku zprávy, aby druhá strana věděla, kolik bajtů potřebuje přečíst. Poté, co je délka odeslána jako primitivní celočíselný typ, lze odeslat bajty.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); System.out.println ("Komunikace je připravena."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}

  • Proudy objektů

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); System.out.println ("Komunikace je připravena."); Řetězec messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}

Vytvořte síťovou aplikaci v jazyce Java Step14
Vytvořte síťovou aplikaci v jazyce Java Step14

Krok 14. Zaznamenat odeslanou zprávu

Pro účely protokolování vytiskněte na konzolu, že byla zpráva odeslána.

  • Datové toky

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = nový Socket (hostitel, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); System.out.println ("Komunikace je připravena."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + nový řetězec (messageOut)); }}

  • Proudy objektů

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); Řetězec messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + messageOut); }}

Vytvořte síťovou aplikaci v jazyce Java Step15
Vytvořte síťovou aplikaci v jazyce Java Step15

Krok 15. Přečtěte si zprávu

Přečtěte data ze vstupního proudu a převeďte je. Protože přesně známe typ odesílaných dat, vytvoříme buď

Tětiva

z

byte

nebo obsazení

Objekt

na

Tětiva

bez kontroly, v závislosti na použitém streamu.

  • Datové toky

    Protože byla odeslána první délka a poté bajty, musí být čtení provedeno ve stejném pořadí. V případě, že je délka nulová, není co číst. Objekt je deserializován, když jsou bajty převedeny zpět na instanci, v tomto případě

    Tětiva

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + nový řetězec (messageOut)); int délka = serverIn.readInt (); if (délka> 0) {byte messageIn = nový byte [délka]; serverIn.readFully (messageIn, 0, messageIn.length); }}}

  • Proudy objektů

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); Řetězec messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + messageOut); Řetězec messageIn = (Řetězec) serverIn.readObject (); }}

Vytvořte síťovou aplikaci v jazyce Java Step16
Vytvořte síťovou aplikaci v jazyce Java Step16

Krok 16. Protokol přečtené zprávy

Pro účely protokolování vytiskněte na konzolu, že zpráva byla přijata, a vytiskněte její obsah.

  • Datové toky

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); DataOutputStream clientOut = nový DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = nový DataInputStream (client.getInputStream ()); DataOutputStream serverOut = nový DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = nový DataInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + nový řetězec (messageOut)); int délka = serverIn.readInt (); if (délka> 0) {byte messageIn = nový byte [délka]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Zpráva přijatá od klienta:" + nový řetězec (messageIn)); }}}

  • Proudy objektů

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); ObjectOutputStream clientOut = nový ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = nový ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nový ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nový ObjectInputStream (connection.getInputStream ()); System.out.println („Komunikace je připravena.“); Řetězec messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Zpráva odeslaná na server:" + messageOut); Řetězec messageIn = (Řetězec) serverIn.readObject (); System.out.println ("Zpráva přijatá od klienta:" + messageIn); }}

Vytvořte síťovou aplikaci v jazyce Java Step17
Vytvořte síťovou aplikaci v jazyce Java Step17

Krok 17. Odpojte připojení

Připojení se přeruší, když jedna strana zavře své streamy. V Javě se zavřením výstupního proudu uzavře také související soket a vstupní proud. Jakmile strana na druhém konci zjistí, že je připojení mrtvé, musí také ukončit svůj výstupní proud, aby se zabránilo úniku paměti.

// kód vynechán import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); // kód vynechán System.out.println ("Komunikace je připravena."); // kód vynechán clientOut.close (); serverOut.close (); }}

Vytvořte síťovou aplikaci v jazyce Java Step18 V2
Vytvořte síťovou aplikaci v jazyce Java Step18 V2

Krok 18. Odpojení protokolu

Pro účely protokolování byly odpojeny připojení ke konzole tisku.

// kód vynechán import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); // kód vynechán System.out.println ("Komunikace je připravena."); // kód vynechán clientOut.close (); serverOut.close (); System.out.println ("Připojení uzavřeno."); }}

Vytvořte síťovou aplikaci v jazyce Java Step19
Vytvořte síťovou aplikaci v jazyce Java Step19

Krok 19. Ukončete server

Připojení jsou odpojena, ale server je stále v provozu. Tak jako

ServerSocket

není spojen s žádným streamem, musí být explicitně uzavřen voláním

zavřít()

metoda.

// kód vynechán import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); // kód vynechán System.out.println ("Komunikace je připravena."); // kód vynechán clientOut.close (); serverOut.close (); System.out.println ("Připojení uzavřeno."); server.close (); }}

Vytvořte síťovou aplikaci v jazyce Java Step20
Vytvořte síťovou aplikaci v jazyce Java Step20

Krok 20. Protokolování ukončení serveru

Pro účely protokolování byl tisk na server konzoly ukončen.

// kód vynechán import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; ServerSocket server = nový ServerSocket (port, 50, InetAddress.getByName (hostitel)); System.out.println ("Server spuštěn."); Socket client = new Socket (host, port); System.out.println ("Připojování k serveru …"); Soketové připojení = server.accept (); System.out.println ("Připojení navázáno."); // kód vynechán System.out.println ("Komunikace je připravena."); // kód vynechán clientOut.close (); serverOut.close (); System.out.println ("Připojení uzavřeno."); server.close (); System.out.println ("Server ukončen."); }}

Vytvořte síťovou aplikaci v jazyce Java Step21
Vytvořte síťovou aplikaci v jazyce Java Step21

Krok 21. Zkompilujte a spusťte

Protokolování nám umožnilo zjistit, zda byla aplikace úspěšná nebo ne. Očekávaný výkon:

Server spuštěn. Připojování k serveru … Připojení navázáno. Komunikace je připravena. Zpráva odeslána na server: Hello World Zpráva od klienta přijata: Hello World Connections ukončena. Server ukončen.

V případě, že váš výstup není stejný jako výše, což se pravděpodobně nestane, existuje několik řešení:

  • Pokud se výstup zastaví na řádku

    Spojení navázáno.

    a používají se toky objektů, vypláchněte každý

    ObjectOutputStream

  • bezprostředně po inicializaci, protože záhlaví z nějakého důvodu nebyla odeslána.
  • Pokud se tisk vytiskne

    java.net. BindException: Adresa se již používá

  • zvolte jiné číslo portu, protože zadané je již použito.

Tipy

  • Připojení k serveru v jiné síti se provádí připojením k externí IP adrese zařízení se serverem, který má předaný port.
  • Připojení k serveru ve stejné síti se provádí buď připojením k soukromé IP adrese zařízení se serverem, nebo přesměrováním portu a připojením k externí IP adrese zařízení.
  • Existuje software, například Hamachi, který umožňuje připojení k serveru v jiné síti bez přeposílání portu, ale vyžaduje instalaci softwaru na obě zařízení.

Příklady

Síťové aplikace, které používají blokování vstupu/výstupu, musí používat vlákna. Následující příklady ukazují minimalistickou implementaci serveru a klienta s vlákny. Síťový kód je v zásadě stejný jako v článku kromě toho, že některé úryvky byly synchronizovány, přesunuty do vláken a řeší se výjimky.

Server.java

import java.io. IOException; import java.net. InetAddress; import java.net. ServerSocket; import java.net. SocketException; import java.net. UnknownHostException; import java.util. ArrayList; import java.util. Collections; import java.util. List; /*** Třída {@code Server} představuje koncový bod serveru v síti. {@code Server}, jakmile je vázán na určitou IP * adresu a port, naváže spojení s klienty a je schopen s nimi komunikovat nebo je odpojit. *

* Tato třída je bezpečná pro vlákna. * * @version 1.0 * @see Client * @see Connection */ public class Server implementuje Spustitelný {soukromý server ServerSocket; soukromý seznam připojení; vlákno soukromého vlákna; private final Object connectionsLock = nový Object (); /** * Konstruuje {@code Server}, který interaguje s klienty na zadaném názvu hostitele a portu se zadanou * požadovanou maximální délkou fronty příchozích klientů. * * @param host Adresa hostitele k použití. * @param port Číslo portu, který se má použít. * @param backlog Požadovaná maximální délka fronty příchozích klientů. * @throws NetworkException Pokud dojde ke chybě při spouštění serveru. */ public Server (String host, int port, int backlog) hodí NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {throw new NetworkException ("Název hostitele nelze přeložit:" + host, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Číslo portu musí být mezi 0 a 65535 (včetně):" + port); } catch (IOException e) {throw new NetworkException ("Server could not be started.", e); } připojení = Collections.synchronizedList (nový ArrayList ()); vlákno = nové vlákno (toto); vlákno.start (); } /*** Konstruuje {@code Server}, který komunikuje s klienty na zadaném názvu hostitele a portu. * * @param host Adresa hostitele pro vazbu. * @param port Číslo portu pro vazbu. * @throws NetworkException Pokud při spouštění serveru dojde k chybě. */ public Server (String host, int port) hodí NetworkException {this (host, port, 50); } /*** Naslouchá, přijímá a registruje příchozí připojení od klientů. */ @Override public void run () {while (! Server.isClosed ()) {try {connections.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Odesílá data všem registrovaným klientům. * * @param data Data k odeslání. * @throws IllegalStateException Pokud dojde k pokusu o zápis dat, když je server offline. * @throws IllegalArgumentException Pokud jsou data k odeslání nulová. */ public void broadcast (Object data) {if (server.isClosed ()) {throw new IllegalStateException ("Data not sent, server is offline."); } if (data == null) {throw new IllegalArgumentException ("null data"); } synchronizováno (connectionsLock) {for (Connection connection: connections) {try {connection.send (data); System.out.println ("Data byla úspěšně odeslána klientovi."); } catch (NetworkException e) {e.printStackTrace (); }}}} /*** Odešle zprávu o odpojení a odpojí zadaného klienta. * * @param připojení Klient k odpojení. * @throws NetworkException Pokud dojde k chybě při zavírání připojení. */ public void disconnect (Connection connection) throws NetworkException {if (connections.remove (connection)) {connection.close (); }} /*** Odešle všem klientům zprávu o odpojení, odpojí je a ukončí server. */ public void close () vyvolá NetworkException {synchronized (connectionsLock) {for (Connection connection: connections) {try {connection.close (); } catch (NetworkException e) {e.printStackTrace (); }}} connections.clear (); zkuste {server.close (); } catch (IOException e) {throw new NetworkException ("Chyba při zavírání serveru."); } konečně {vlákno.interrupt (); }} /*** Vrátí, zda je server online. * * @return True, pokud je server online. Jinak nepravda. */ public boolean isOnline () {return! server.isClosed (); } /*** Vrací řadu registrovaných klientů. */ public Connection getConnections () {synchronized (connectionsLock) {return connections.toArray (new Connection [connections.size ()]); }}}

Client.java

import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /*** Třída {@code Client} představuje koncový bod klienta v síti. {@code Client}, po připojení k určitému * serveru, bude zaručeně schopen komunikovat pouze se serverem. Zda ostatní klienti získají data * závisí na implementaci serveru. *

* Tato třída je bezpečná pro vlákna. * * @version 1.0 * @viz server * @viz připojení */ klient veřejné třídy {soukromé připojení; /*** Vytvoří {@code Client} připojeného k serveru na zadaném hostiteli a portu. * * @param host Adresa hostitele pro vazbu. * @param port Číslo portu pro vazbu. * @throws NetworkException Pokud dojde ke chybě při spouštění serveru. */ public Client (String host, int port) hodí NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {throw new NetworkException ("Název hostitele nelze přeložit:" + host, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Číslo portu musí být mezi 0 a 65535 (včetně):" + port); } catch (IOException e) {throw new NetworkException ("Server could not be started.", e); }} /*** Odesílá data druhé straně. * * @param data Data k odeslání. * @throws NetworkException Pokud zápis do výstupního proudu selže. * @throws IllegalStateException Pokud dojde k pokusu o zápis dat, když je připojení uzavřeno. * @throws IllegalArgumentException Pokud jsou data k odeslání nulová. * @throws UnsupportedOperationException Pokud se pokoušíte odeslat nepodporovaný datový typ. */ public void send (Objektová data) vyvolá NetworkException {connection.send (data); } /*** Odešle zprávu o odpojení na server a ukončí spojení se serverem. */ public void close () hodí NetworkException {connection.close (); } /*** Vrátí, zda je klient připojen k serveru či nikoli. * * @return True, pokud je klient připojen. Jinak nepravda. */ public boolean isOnline () {return connection.isConnected (); } /*** Vrací instanci klienta {@link Connection}. */ public Connection getConnection () {zpětné připojení; }}

Connection.java

import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; /** * Třída {@code Connection} představuje buď připojení ze serveru na klienta, nebo koncový bod klienta v síti * {@code Connection}, jakmile je připojen, je schopen vyměňovat si data s jinou stranou nebo stranami v závislosti na na implementaci serveru *. *

* Tato třída je bezpečná pro vlákna. * * @version 1.0 * @see Server * @see Client */ public class Připojení implementuje Spustitelné {private Socket socket; soukromý DataOutputStream ven; soukromý DataInputStream v; vlákno soukromého vlákna; private final Object writeLock = nový Object (); private final Objekt readLock = nový Object (); /*** Vytváří {@code Connection} pomocí streamů zadaného {@link Socket}. * * @param socket Socket pro načtení streamů z.*/ public Connection (Socket socket) hodí NetworkException {if (socket == null) {throw new IllegalArgumentException ("null socket"); } this.socket = socket; zkusit {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throw new NetworkException ("Nelze získat přístup k výstupnímu proudu.", e); } zkusit {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throw new NetworkException ("Nelze získat přístup ke vstupnímu proudu.", e); } vlákno = nové vlákno (toto); vlákno.start (); } /*** Čte zprávy, když je spojení s druhou stranou aktivní. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; byte bajtů; synchronizovaný (readLock) {identifier = in.readInt (); int délka = in.readInt (); if (length> 0) {bytes = new byte [length]; in.readFully (bajty, 0, bajty. délka); } else {pokračovat; }} switch (identifier) {case Identifier. INTERNAL: String command = new String (bytes); if (command.equals ("disconnect")) {if (! socket.isClosed ()) {System.out.println ("Disconnection packet prijat."); zkusit {zavřít (); } catch (NetworkException e) {return; } } } přestávka; case Identifier. TEXT: System.out.println ("Přijatá zpráva:" + nový řetězec (bajty)); přestávka; výchozí: System.out.println ("Byla přijata nerozpoznaná data."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}} /*** Odesílá data druhé straně. * * @param data Data k odeslání. * @throws NetworkException Pokud zápis do výstupního proudu selže. * @throws IllegalStateException Pokud dojde k pokusu o zápis dat, když je připojení uzavřeno. * @throws IllegalArgumentException Pokud jsou data k odeslání nulová. * @throws UnsupportedOperationException Pokud se pokoušíte odeslat nepodporovaný datový typ. */ public void send (Object data) throws NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Data not sent, connection is closed."); } if (data == null) {throw new IllegalArgumentException ("null data"); } identifikátor int; byte bajtů; if (datová instance řetězce) {identifier = Identifier. TEXT; bajty = ((String) data).getBytes (); } else {throw new UnsupportedOperationException ("Unsupported data type:" + data.getClass ()); } zkusit {synchronized (writeLock) {out.writeInt (identifier); out.writeInt (bytes.length); out.write (bajty); out.flush (); }} catch (IOException e) {throw new NetworkException ("Data could not be sent.", e); }} /*** Odešle zprávu o odpojení druhé straně a uzavře s ní spojení. */ public void close () hodí NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Připojení je již uzavřeno."); } zkuste {byte message = "odpojit".getBytes (); synchronizované (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (message.length); out.write (zpráva); out.flush (); }} catch (IOException e) {System.out.println ("Zprávu o odpojení nelze odeslat."); } zkusit {synchronized (writeLock) {out.close (); }} catch (IOException e) {throw new NetworkException ("Chyba při zavírání připojení.", e); } konečně {vlákno.interrupt (); }} /*** Vrátí, zda je připojení k druhé straně aktivní. * * @return True, pokud je připojení aktivní. Jinak nepravda. */ public boolean isConnected () {return! socket.isClosed (); }}

Identifier.java

/** * Třída {@code Identifier} obsahuje konstanty používané {@link Connection} pro serializaci a deserializaci dat * odesílaných po síti. * * @version 1.0 * @viz Připojení * / veřejný identifikátor konečné třídy { / ** * Identifikátor pro interní zprávy. */ public static final int INTERNAL = 1; /*** Identifikátor pro textové zprávy. */ public static final int TEXT = 2; }

NetworkException.java

/*** Třída {@code NetworkException} označuje chybu související se sítí. * / public class NetworkException rozšiřuje výjimku { / *** Konstruuje {@code NetworkException} se zprávou {@code null}. * / public NetworkException () {} / *** Vytvoří {@code NetworkException} se zadanou zprávou. * * @param message Zpráva popisující chybu. */ public NetworkException (String message) {super (message); } /*** Vytvoří {@code NetworkException} se zadanou zprávou a příčinou. * * @param message Zpráva popisující chybu. * @param příčina Příčina chyby. */ public NetworkException (String message, Throwable cause) {super (zpráva, příčina); } /*** Vytvoří {@code NetworkException} se zadanou příčinou. * * @param příčina Příčina chyby. */ public NetworkException (vyvolávací příčina) {super (příčina); }}

UsageExample.java

/*** Třída {@code UsageExample} ukazuje využití {@link Server} a {@link Client}. Tento příklad používá * {@link Thread#sleep (long)} k zajištění spuštění každého segmentu, protože rychlé spuštění a zavření způsobí, že některé * segmenty nebudou spuštěny. * * @version 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) throws Exception {String host = "localhost"; int port = 10430; Server server = nový Server (hostitel, port); Klient klienta = nový klient (hostitel, port); Thread.sleep (100L); client.send („Dobrý den.“); server.broadcast („Hej, kámo!“); Thread.sleep (100L); server.disconnect (server.getConnections () [0]); // nebo client.close () pro odpojení od klienta server.close (); }}

Doporučuje: