Come creare un'applicazione di rete in Java (con immagini)

Sommario:

Come creare un'applicazione di rete in Java (con immagini)
Come creare un'applicazione di rete in Java (con immagini)

Video: Come creare un'applicazione di rete in Java (con immagini)

Video: Come creare un'applicazione di rete in Java (con immagini)
Video: Trucco per velocizzare il tuo telefonino #tipsandroid #tricks #android 2024, Maggio
Anonim

Scrivere codice che viene eseguito su un determinato dispositivo è molto soddisfacente. Ma scrivere codice che viene eseguito su più dispositivi che comunicano tra loro è semplicemente affermativo. Questo articolo ti insegnerà come connettere e scambiare messaggi sulla rete utilizzando il protocollo di controllo della trasmissione (TCP).

In questo articolo, configurerai un'applicazione che collegherà il tuo computer a se stesso e, in sostanza, lo farà impazzire - parlerà da solo. Imparerai anche la differenza tra i due flussi più utilizzati per il networking in Java e come funzionano.

Flussi di dati e oggetti

Prima di immergersi nel codice, è necessario distinguere la differenza tra i due flussi utilizzati nell'articolo.

Flussi di dati

I flussi di dati elaborano stringhe e tipi di dati primitivi. I dati inviati tramite flussi di dati devono essere serializzati e deserializzati manualmente, il che rende più difficile il trasferimento di dati complessi. Tuttavia, i flussi di dati possono comunicare con server e client scritti in linguaggi diversi da Java. I flussi grezzi sono simili ai flussi di dati in questo aspetto, ma i flussi di dati assicurano che i dati siano formattati in un modo indipendente dalla piattaforma, il che è vantaggioso perché entrambe le parti saranno in grado di leggere i dati inviati.

Flussi di oggetti

I flussi di oggetti elaborano tipi di dati primitivi e oggetti che implementano

serializzabile

interfaccia. I dati inviati su flussi di oggetti vengono serializzati e deserializzati automaticamente, il che semplifica il trasferimento di dati complessi. Tuttavia, i flussi di oggetti possono comunicare solo con server e client scritti in Java. Anche,

ObjectOutputStream

al momento dell'inizializzazione, invia un'intestazione al

InputStream

dell'altra parte che, al momento dell'inizializzazione, blocca l'esecuzione fino alla ricezione dell'intestazione.

Passi

Creare un'applicazione di rete in Java Step1
Creare un'applicazione di rete in Java Step1

Passaggio 1. Crea una classe

Crea una classe e chiamala come preferisci. In questo articolo, sarà chiamato

NetworkAppEsempio

public class NetworkAppExample { }

Creare un'applicazione di rete in Java Step2
Creare un'applicazione di rete in Java Step2

Passaggio 2. Creare un metodo principale

Crea un metodo principale e dichiara che potrebbe generare eccezioni di

Eccezione

tipo e qualsiasi sottoclasse di esso - tutte le eccezioni. Questa è considerata una cattiva pratica, ma è accettabile per gli esempi barebone.

public class NetworkAppExample { public static void main(String args) genera un'eccezione { } }

Creare un'applicazione di rete in Java Step3
Creare un'applicazione di rete in Java Step3

Passaggio 3. Dichiarare l'indirizzo del server

Questo esempio utilizzerà l'indirizzo host locale e un numero di porta arbitrario. Il numero di porta deve essere compreso in un intervallo compreso tra 0 e 65535 (incluso). Tuttavia, i numeri di porta da evitare vanno da 0 a 1023 (inclusi) perché sono porte di sistema riservate.

public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; } }

Creare un'applicazione di rete in Java Step4
Creare un'applicazione di rete in Java Step4

Passaggio 4. Creare un server

Il server è vincolato all'indirizzo e alla porta e ascolta le connessioni in entrata. A Giava,

ServerSocket

rappresenta l'endpoint lato server e la sua funzione accetta nuove connessioni.

ServerSocket

non ha flussi per la lettura e l'invio dei dati perché non rappresenta la connessione tra un server e un client.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); } }

Creare un'applicazione di rete in Java Step5
Creare un'applicazione di rete in Java Step5

Passaggio 5. Inizio del server di registrazione

Ai fini della registrazione, stampare sulla console che il server è stato avviato.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); } }

Creare un'applicazione di rete in Java Step6
Creare un'applicazione di rete in Java Step6

Passaggio 6. Creare un cliente

Il client è legato all'indirizzo e alla porta di un server e ascolta i pacchetti (messaggi) dopo che è stata stabilita la connessione. A Giava,

Presa

rappresenta un endpoint lato client connesso al server o una connessione (dal server) al client e viene utilizzato per comunicare con la parte dall'altra parte.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); } }

Creare un'applicazione di rete in Java Step7
Creare un'applicazione di rete in Java Step7

Passaggio 7. Registrare il tentativo di connessione

Ai fini della registrazione, stampare sulla console che è stata tentata la connessione.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); } }

Creare un'applicazione di rete in Java Step8
Creare un'applicazione di rete in Java Step8

Passaggio 8. Stabilire la connessione

I client non si connetteranno mai a meno che il server non ascolti e accetti, in altre parole, stabilisca connessioni. In Java, le connessioni vengono stabilite utilizzando

accettare()

metodo di

ServerSocket

classe. Il metodo bloccherà l'esecuzione finché un client non si connette.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); } }

Creare un'applicazione di rete in Java Step9
Creare un'applicazione di rete in Java Step9

Passaggio 9. Registrare la connessione stabilita

Ai fini della registrazione, stampare sulla console che è stata stabilita la connessione tra server e client.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); } }

Creare un'applicazione di rete in Java Step10
Creare un'applicazione di rete in Java Step10

Passaggio 10. Preparare i flussi di comunicazione

La comunicazione avviene su flussi e, in questa applicazione, i flussi grezzi di (connessione da) server (a client) e client devono essere concatenati a flussi di dati o oggetti. Ricorda, entrambe le parti devono utilizzare lo stesso tipo di flusso.

  • Flussi di dati

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); } }

  • Flussi di oggetti

    Quando vengono utilizzati più flussi di oggetti, i flussi di input devono essere inizializzati nello stesso ordine dei flussi di output perché

    ObjectOutputStream

    invia un'intestazione all'altra parte e

    ObjectInputStream

    blocca l'esecuzione finché non legge l'intestazione.

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); } }

    L'ordine come specificato nel codice sopra potrebbe essere più facile da ricordare: prima inizializza i flussi di output, quindi i flussi di input nello stesso ordine. Tuttavia, un altro ordine per l'inizializzazione dei flussi di oggetti è il seguente:

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

Creare un'applicazione di rete in Java Step11
Creare un'applicazione di rete in Java Step11

Passaggio 11. Registrare che la comunicazione è pronta

Ai fini della registrazione, stampare sulla console che la comunicazione è pronta.

// codice omesso import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); // codice omesso System.out.println("La comunicazione è pronta."); } }

Creare un'applicazione di rete in Java Step12
Creare un'applicazione di rete in Java Step12

Passaggio 12. Crea un messaggio

In questa applicazione,

Ciao mondo

il testo verrà inviato al server come

byte

o

Corda

. Dichiarare una variabile del tipo che dipende dal flusso utilizzato. Utilizzo

byte

per flussi di dati e

Corda

per flussi di oggetti.

  • Flussi di dati

    Utilizzando i flussi di dati, la serializzazione viene eseguita convertendo gli oggetti in tipi di dati primitivi o a

    Corda

    . In questo caso,

    Corda

    viene convertito in

    byte

    invece di scrivere usando

    writeBytes()

    metodo per mostrare come sarebbe fatto con altri oggetti, come immagini o altri file.

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); byte messageOut = "Hello World".getBytes(); } }

  • Flussi di oggetti

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); String messageOut = "Hello World"; } }

Creare un'applicazione di rete in Java Step13
Creare un'applicazione di rete in Java Step13

Passaggio 13. Invia il messaggio

Scrivi i dati nel flusso di output e scarica il flusso per assicurarti che i dati siano stati scritti interamente.

  • Flussi di dati

    La lunghezza di un messaggio deve essere inviata prima in modo che l'altra parte sappia quanti byte deve leggere. Dopo che la lunghezza è stata inviata come tipo intero primitivo, è possibile inviare i byte.

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); byte messageOut = "Hello World".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write(messageOut); clientOut.flush(); } }

  • Flussi di oggetti

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); String messageOut = "Hello World"; clientOut.writeObject(messageOut); clientOut.flush(); } }

Creare un'applicazione di rete in Java Step14
Creare un'applicazione di rete in Java Step14

Passaggio 14. Registra il messaggio inviato

Ai fini della registrazione, stampare sulla console che il messaggio è stato inviato.

  • Flussi di dati

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); byte messageOut = "Hello World".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + new String(messageOut)); } }

  • Flussi di oggetti

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); String messageOut = "Hello World"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + messageOut); } }

Creare un'applicazione di rete in Java Step15
Creare un'applicazione di rete in Java Step15

Passaggio 15. Leggi il messaggio

Leggere i dati dal flusso di input e convertirli. Poiché conosciamo esattamente il tipo di dati inviati, creeremo un

Corda

a partire dal

byte

o cast

Oggetto

a

Corda

senza controllo, a seconda del flusso utilizzato.

  • Flussi di dati

    Poiché la lunghezza è stata inviata prima e i byte dopo, la lettura deve essere eseguita nello stesso ordine. Nel caso in cui la lunghezza sia zero, non c'è nulla da leggere. L'oggetto viene deserializzato quando i byte vengono riconvertiti in un'istanza, in questo caso, di

    Corda

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); byte messageOut = "Hello World".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + new String(messageOut)); int lunghezza = serverIn.readInt(); if (lunghezza > 0) { byte messageIn = nuovo byte[lunghezza]; serverIn.readFully(messageIn, 0, messageIn.length); } } }

  • Flussi di oggetti

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); String messageOut = "Hello World"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + messageOut); String messageIn = (String) serverIn.readObject(); } }

Creare un'applicazione di rete in Java Step16
Creare un'applicazione di rete in Java Step16

Passaggio 16. Registra il messaggio letto

Ai fini della registrazione, stampare sulla console che il messaggio è stato ricevuto e stamparne il contenuto.

  • Flussi di dati

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); byte messageOut = "Hello World".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + new String(messageOut)); int lunghezza = serverIn.readInt(); if (lunghezza > 0) { byte messageIn = nuovo byte[lunghezza]; serverIn.readFully(messageIn, 0, messageIn.length); System.out.println("Messaggio ricevuto dal client: " + new String(messageIn)); } } }

  • Flussi di oggetti

    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) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("La comunicazione è pronta."); String messageOut = "Hello World"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Messaggio inviato al server: " + messageOut); String messageIn = (String) serverIn.readObject(); System.out.println("Messaggio ricevuto dal cliente: " + messageIn); } }

Creare un'applicazione di rete in Java Step17
Creare un'applicazione di rete in Java Step17

Passaggio 17. Scollegare le connessioni

La connessione viene disconnessa quando una delle parti chiude i propri flussi. In Java, chiudendo il flusso di output, vengono chiusi anche il socket associato e il flusso di input. Una volta che una parte dall'altra parte scopre che la connessione è morta, deve chiudere anche il flusso di output per evitare perdite di memoria.

// codice omesso import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); // codice omesso System.out.println("La comunicazione è pronta."); // codice omesso clientOut.close(); serverOut.close(); } }

Creare un'applicazione di rete in Java Step18 V2
Creare un'applicazione di rete in Java Step18 V2

Passaggio 18. Disconnessione del registro

Ai fini della registrazione, le connessioni di stampa sulla console sono state disconnesse.

// codice omesso import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); // codice omesso System.out.println("La comunicazione è pronta."); // codice omesso clientOut.close(); serverOut.close(); System.out.println("Connessioni chiuse."); } }

Crea un'applicazione di rete in Java Step19
Crea un'applicazione di rete in Java Step19

Passaggio 19. Termina il server

Le connessioni sono disconnesse, ma il server è ancora attivo e funzionante. Come

ServerSocket

non è associato ad alcun flusso, deve essere chiuso esplicitamente chiamando

chiudere()

metodo.

// codice omesso import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); // codice omesso System.out.println("La comunicazione è pronta."); // codice omesso clientOut.close(); serverOut.close(); System.out.println("Connessioni chiuse."); server.close(); } }

Crea un'applicazione di rete in Java Step20
Crea un'applicazione di rete in Java Step20

Passaggio 20. Terminazione del server di registro

Ai fini della registrazione, la stampa sul server della console è stata terminata.

// codice omesso import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; ServerSocket server = nuovo ServerSocket(port, 50, InetAddress.getByName(host)); System.out.println("Server avviato."); Socket client = nuovo Socket (host, porta); System.out.println("Connessione al server…"); Connessione socket = server.accept(); System.out.println("Connessione stabilita."); // codice omesso System.out.println("La comunicazione è pronta."); // codice omesso clientOut.close(); serverOut.close(); System.out.println("Connessioni chiuse."); server.close(); System.out.println("Server terminato."); } }

Crea un'applicazione di rete in Java Step21
Crea un'applicazione di rete in Java Step21

Passaggio 21. Compila ed esegui

La registrazione ci ha permesso di sapere se l'applicazione ha avuto successo o meno. Uscita prevista:

Server avviato. Connessione al server… Connessione stabilita. La comunicazione è pronta. Messaggio inviato al server: Hello World Messaggio ricevuto dal client: Hello World Connessioni chiuse. Server terminato.

Nel caso in cui il tuo output non sia come quello sopra, il che è improbabile che accada, ci sono alcune soluzioni:

  • Se l'uscita si ferma sulla linea

    Connessione stabilita.

    e vengono utilizzati i flussi di oggetti, svuota ciascuno

    ObjectOutputStream

  • subito dopo l'inizializzazione perché le intestazioni, per qualche motivo, non sono state inviate.
  • Se l'output viene stampato

    java.net. BindException: indirizzo già in uso

  • scegli un numero di porta diverso perché quello specificato è già utilizzato.

Suggerimenti

  • La connessione a un server su una rete diversa viene eseguita collegandosi all'indirizzo IP esterno di un dispositivo che esegue il server che dispone di una porta di inoltro.
  • La connessione a un server sulla stessa rete viene eseguita collegandosi all'indirizzo IP privato di un dispositivo che esegue il server o inoltrando una porta e connettendosi all'indirizzo IP esterno del dispositivo.
  • Esistono software, come Hamachi, che consentono di connettersi al server su una rete diversa senza inoltrare una porta, ma richiedono l'installazione del software su entrambi i dispositivi.

Esempi

Le applicazioni di rete che utilizzano il blocco di input/output devono utilizzare i thread. Gli esempi seguenti mostrano un server minimalista e un'implementazione client con thread. Il codice di rete è essenzialmente lo stesso dell'articolo, tranne per il fatto che alcuni frammenti sono stati sincronizzati, spostati nei thread e gestite le eccezioni.

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; /** * La classe {@code Server} rappresenta un punto finale del server in una rete. {@code Server} una volta associato a un determinato indirizzo IP * e porta, stabilisce connessioni con i client ed è in grado di comunicare con loro o disconnetterli. *

* Questa classe è thread-safe. * * @version 1.0 * @see Client * @see Connection */ public class Server implementa Runnable { private ServerSocket server; lista privata connessioni; thread privato; private final Object connectionLock = new Object(); /** * Costruisce un {@code Server} che interagisce con i client sul nome host e sulla porta specificati con la * lunghezza massima richiesta specificata di una coda di client in entrata. * * @param host Indirizzo host da utilizzare. * @param port Numero di porta da utilizzare. * @param backlog Lunghezza massima richiesta della coda dei client in entrata. * @throws NetworkException Se si verifica un errore durante l'avvio di un server. */ public Server(String host, int port, int backlog) genera NetworkException { try { server = new ServerSocket(port, backlog, InetAddress.getByName(host)); } catch (UnknownHostException e) { throw new NetworkException("Impossibile risolvere il nome host: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Il numero di porta deve essere compreso tra 0 e 65535 (incluso): " + port); } catch (IOException e) { throw new NetworkException("Impossibile avviare il server.", e); } connessioni = Collections.synchronizedList(new ArrayList()); thread = nuovo Thread (questo); thread.start(); } /** * Costruisce un {@code Server} che interagisce con i client sul nome host e sulla porta specificati. * * @param host Indirizzo host da associare. * @param port Numero di porta da associare. * @throws NetworkException Se si verificano errori durante l'avvio di un server. */ public Server(String host, int port) genera NetworkException { this(host, port, 50); } /** * Ascolta, accetta e registra le connessioni in entrata dai client. */ @Override public void run() { while (!server.isClosed()) { try { connection.add(new Connection(server.accept())); } catch (SocketException e) { if (!e.getMessage().equals("Socket chiuso")) { e.printStackTrace(); } } catch (NetworkException | IOException e) { e.printStackTrace(); } } } /** * Invia i dati a tutti i clienti registrati. * * @param data Dati da inviare. * @throws IllegalStateException Se si tenta di scrivere dati quando il server è offline. * @throws IllegalArgumentException Se i dati da inviare sono null. */ public void broadcast(Object data) { if (server.isClosed()) { throw new IllegalStateException("Dati non inviati, il server non è in linea."); } if (data == null) { throw new IllegalArgumentException("dati nulli"); } sincronizzato (connectionsLock) { for (Connection connection: connection) { try { connection.send(data); System.out.println("Dati inviati al cliente con successo."); } catch (NetworkException e) { e.printStackTrace(); } } } } /** * Invia un messaggio di disconnessione e disconnette il client specificato. * * @param connection Client da disconnettere. * @throws NetworkException Se si verifica un errore durante la chiusura della connessione. */ public void disconnect (Connection connection) genera NetworkException { if (connections.remove(connection)) { connection.close(); } } /** * Invia un messaggio di disconnessione a tutti i client, li disconnette e termina il server. */ public void close() lancia NetworkException { sincronizzato (connectionsLock) { for (Connection connection: connection) { try { connection.close(); } catch (NetworkException e) { e.printStackTrace(); } } } connection.clear(); prova { server.close(); } catch (IOException e) { throw new NetworkException("Errore durante la chiusura del server."); } infine { thread.interrupt(); } } /** * Restituisce se il server è online o meno. * * @return True se il server è online. Falso, altrimenti. */ public boolean isOnline() { return !server.isClosed(); } /** * Restituisce un array di client registrati. */ public Connection getConnections() { sincronizzato (connectionsLock) { return connection.toArray(new Connection[connections.size()]); } } }

Client.java

import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /** * La classe {@code Client} rappresenta un endpoint client in una rete. {@code Client}, una volta connesso a un determinato * server, è garantito che sarà in grado di comunicare solo con il server. Il fatto che altri client ricevano o meno i dati * dipende dall'implementazione del server. *

* Questa classe è thread-safe. * * @version 1.0 * @see Server * @see Connection */ public class Client { private Connection connection; /** * Costruisce un {@code Client} connesso al server sull'host e sulla porta specificati. * * @param host Indirizzo host da associare. * @param port Numero di porta da associare. * @throws NetworkException Se si verifica un errore durante l'avvio di un server. */ public Client(String host, int port) genera NetworkException { try { connection = new Connection(new Socket(host, port)); } catch (UnknownHostException e) { throw new NetworkException("Impossibile risolvere il nome host: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Il numero di porta deve essere compreso tra 0 e 65535 (incluso): " + port); } catch (IOException e) { throw new NetworkException("Impossibile avviare il server.", e); } } /** * Invia i dati all'altra parte. * * @param data Dati da inviare. * @throws NetworkException Se la scrittura nel flusso di output fallisce. * @throws IllegalStateException Se si tenta di scrivere dati alla chiusura della connessione. * @throws IllegalArgumentException Se i dati da inviare sono null. * @throws UnsupportedOperationException Se si tenta di inviare un tipo di dati non supportato. */ public void send (dati oggetto) genera NetworkException { connection.send (dati); } /** * Invia un messaggio di disconnessione e chiude la connessione con il server. */ public void close() lancia NetworkException { connection.close(); } /** * Restituisce se il client è connesso o meno al server. * * @return True se il client è connesso. Falso, altrimenti. */ public boolean isOnline() { return connection.isConnected(); } /** * Restituisce l'istanza {@link Connection} del client. */ connessione pubblica getConnection() { connessione di ritorno; } }

Connessione.java

import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; /** * La classe {@code Connection} rappresenta o una connessione da server a client o un client end-point in una rete * {@code Connection}, una volta connesso, è in grado di scambiare dati con altre parti, a seconda su un server * implementazione. *

* Questa classe è thread-safe. * * @version 1.0 * @see Server * @see Client */ public class Connection implementa Runnable { private Socket socket; uscita DataOutputStream privata; DataInputStream privato in; thread privato; oggetto finale privato writeLock = new Object(); oggetto finale privato readLock = new Object(); /** * Costruisce {@code Connection} utilizzando i flussi di un {@link Socket} specificato. * * @param socket Socket da cui prelevare i flussi.*/ public Connection(Socket socket) lancia NetworkException { if (socket == null) { throw new IllegalArgumentException("null socket"); } this.socket = socket; try { out = new DataOutputStream(socket.getOutputStream()); } catch (IOException e) { throw new NetworkException("Impossibile accedere al flusso di output.", e); } try { in = new DataInputStream(socket.getInputStream()); } catch (IOException e) { throw new NetworkException("Impossibile accedere al flusso di input.", e); } thread = nuovo Thread (questo); thread.start(); } /** * Legge i messaggi mentre la connessione con l'altra parte è attiva. */ @Override public void run() { while (!socket.isClosed()) { try { int identificatore; byte byte; sincronizzato (readLock) { identificatore = in.readInt(); int lunghezza = in.readInt(); if (lunghezza > 0) { byte = nuovo byte[lunghezza]; in.readFully(byte, 0, byte.lunghezza); } else { continua; } } switch (identificatore) { case Identifier. INTERNAL: String command = new String(bytes); if (command.equals("disconnect")) { if (!socket.isClosed()) { System.out.println("Pacchetto di disconnessione ricevuto."); prova {chiudi(); } catch (NetworkException e) { return; } } } rottura; case Identifier. TEXT: System.out.println("Messaggio ricevuto: " + new String(bytes)); rottura; default: System.out.println("Dati ricevuti non riconosciuti."); } } catch (SocketException e) { if (!e.getMessage().equals("Socket chiuso")) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } } /** * Invia i dati all'altra parte. * * @param data Dati da inviare. * @throws NetworkException Se la scrittura nel flusso di output fallisce. * @throws IllegalStateException Se si tenta di scrivere dati alla chiusura della connessione. * @throws IllegalArgumentException Se i dati da inviare sono null. * @throws UnsupportedOperationException Se si tenta di inviare un tipo di dati non supportato. */ public void send(Object data) throws NetworkException { if (socket.isClosed()) { throw new IllegalStateException("Dati non inviati, connessione chiusa."); } if (data == null) { throw new IllegalArgumentException("dati nulli"); } int identificatore; byte byte; if (istanza di dati di String) { identificatore = Identificatore. TEXT; byte = ((Stringa) dati).getBytes(); } else { throw new UnsupportedOperationException("Tipo di dati non supportato: " + data.getClass()); } try { sincronizzato (writeLock) { out.writeInt(identificatore); out.writeInt(bytes.length); out.write(byte); out.flush(); } } catch (IOException e) { throw new NetworkException("Impossibile inviare i dati.", e); } } /** * Invia un messaggio di disconnessione e chiude la connessione con l'altra parte. */ public void close() lancia NetworkException { if (socket.isClosed()) { throw new IllegalStateException("La connessione è già chiusa."); } prova { byte messaggio = "disconnetti".getBytes(); sincronizzato (writeLock) { out.writeInt(Identifier. INTERNAL); out.writeInt(messaggio.lunghezza); out.write(messaggio); out.flush(); } } catch (IOException e) { System.out.println("Impossibile inviare il messaggio di disconnessione."); } try { sincronizzato (writeLock) { out.close(); } } catch (IOException e) { throw new NetworkException("Errore durante la chiusura della connessione.", e); } infine { thread.interrupt(); } } /** * Restituisce se la connessione con l'altra parte è attiva o meno. * * @return True se la connessione è attiva. Falso, altrimenti. */ public boolean isConnected() { return !socket.isClosed(); } }

Identificatore.java

/** * La classe {@code Identifier} contiene le costanti utilizzate da {@link Connection} per serializzare e deserializzazione dei dati * inviati sulla rete. * * @version 1.0 * @see Connection */ public final class Identifier { /** * Identificatore per i messaggi interni. */ public static final int INTERNAL = 1; /** * Identificatore per i messaggi testuali. */ public static final int TEXT = 2; }

NetworkException.java

/** * La classe {@code NetworkException} indica un errore relativo alla rete. */ public class NetworkException estende l'eccezione { /** * Costruisce un {@code NetworkException} con {@code null} come messaggio. */ public NetworkException() { } /** * Costruisce un {@code NetworkException} con il messaggio specificato. * * @param message Un messaggio per descrivere l'errore. */ public NetworkException(String message) { super(message); } /** * Costruisce un {@code NetworkException} con il messaggio e la causa specificati. * * @param message Un messaggio per descrivere l'errore. * @param causa Una causa di errore. */ public NetworkException(String message, Throwable cause) { super(message, cause); } /** * Costruisce un {@code NetworkException} con la causa specificata. * * @param causa Una causa di errore. */ public NetworkException(Throwable cause) { super(causa); } }

Esempio di utilizzo.java

/** * La classe {@code UsageExample} mostra l'utilizzo di {@link Server} e {@link Client}. Questo esempio utilizza * {@link Thread#sleep(long)} per garantire che ogni segmento venga eseguito perché l'avvio e la chiusura rapidi fanno sì che alcuni * segmenti non vengano eseguiti. * * @version 1.0 * @see Server * @see Client */ public class UsageExample { public static void main(String args) genera un'eccezione { String host = "localhost"; porta int = 10430; Server server = nuovo Server (host, porta); Client client = nuovo Client (host, porta); Thread.sleep(100L); client.send("Ciao."); server.broadcast("Ehi, amico!"); Thread.sleep(100L); server.disconnect(server.getConnections()[0]); // o client.close() per disconnettersi dal lato client server.close(); } }

Consigliato: