In questa guida, JAVA – Applicazioni con SOCKET UDP, realizziamo delle applicazioni di rete a livello di Socket con protocollo UDP in JAVA. Qui in basso e nella sezione download si possono scaricare i sorgenti

In questa guida, JAVA – Applicazioni con SOCKET UDP, realizziamo delle applicazioni di rete a livello di Socket con protocollo UDP in JAVA. Qui in basso e nella sezione download si possono scaricare i sorgenti


main.zip (330 download )

Sommario

Introduzione

Prima di iniziare è utile preparare l’ambiente di lavoro. Tutte le indicazioni sono disponibili alla pagina: https://profgiagnotti.it/guida-alla-creazione-dellambiente-di-lavoro-per-applicazioni-con-socket-in-java/

Capitolo 1: Introduzione al Protocollo UDP

Il protocollo UDP (User Datagram Protocol) ha caratteristiche diverse dal protocollo TCP (Transmission Control Protocol). A differenza di TCP, UDP non è orientato alla connessione, il che significa che tra due host non viene stabilito uno stream stabile.

L’avvio di una comunicazione avviene senza handshaking e la consegna dei dati non è garantita. Tuttavia, vengono eseguiti controlli sull’integrità dei dati, come avviene in TCP.

Uno dei principali vantaggi di UDP è che, grazie alla sua semplicità, offre un servizio molto rapido e non richiede il processo di handshaking. Per questo motivo, viene spesso utilizzato per applicazioni come il DNS (Domain Name System).

Caratteristiche della comunicazione UDP

Nella comunicazione dati “connectionless” o “datagram”, il canale ha le seguenti proprietà:

  • Trasporta messaggi, ma non garantisce l’affidabilità della trasmissione.
  • Non è affidabile: i pacchetti possono andare persi.
  • Ha il socket condiviso: più applicazioni possono condividere lo stesso socket.
  • Non preserva l’ordine delle informazioni: i pacchetti possono arrivare in un ordine diverso rispetto all’invio.

Inoltre, l’ordine di arrivo dei pacchetti non è necessariamente lo stesso dell’ordine di invio.


Struttura di un sistema Client-Server UDP

Realizzare un sistema Client-Server UDP in Java consiste nell’implementare un programma che segue alcuni passi fondamentali.

Per il Client:

  1. Crea il socket.
  2. Manda una richiesta sul socket (contenente indirizzo, porta e messaggio).
  3. Riceve i dati dal socket.
  4. Chiude il socket.

Per il Server:

  1. Crea il socket.
  2. Entra in un ciclo in cui:
    • Rimane in attesa delle richieste in arrivo.
    • Riceve il messaggio dal socket.
    • Invia la risposta al client che ha effettuato la richiesta.
  3. Chiude il socket.

La comunicazione UDP in Java

La comunicazione tramite UDP in Java viene gestita attraverso la classe DatagramSocket, che permette di creare socket per la trasmissione di pacchetti DatagramPacket.

La classe DatagramSocket

La classe DatagramSocket usa il protocollo UDP per trasmettere dati attraverso i socket.
Permette a un client di connettersi a una determinata porta di un host per leggere e scrivere dati incapsulati nei pacchetti DatagramPacket.
L’indirizzo dell’host destinatario è contenuto all’interno del DatagramPacket.

Principali metodi di DatagramSocket

  • Metodi costruttori:
DatagramSocket() throws SocketException   // Crea un socket UDP senza specificare una porta
DatagramSocket(int porta) throws SocketException   // Crea un socket UDP associato a una porta specifica
  • Metodi per trasmettere e ricevere dati:
void send(DatagramPacket pacchettoDati) throws IOException  // Invia un pacchetto di dati
void receive(DatagramPacket pacchettoDati) throws IOException  // Riceve un pacchetto di dati
  • Metodo per chiudere la connessione:
void close()  // Chiude il socket

La classe DatagramPacket

La classe DatagramPacket permette di rappresentare i pacchetti UDP da inviare e ricevere sui socket di tipo datagram.

Principali metodi di DatagramPacket

  • Metodo costruttore per inviare un pacchetto:
public DatagramPacket(byte buffer[], int lunghezza, InetAddress indirizzo, int porta)

Il client crea un oggetto DatagramPacket passando al costruttore:

  • Il contenuto del messaggio (un array di byte).
  • L’indirizzo IP del server.
  • Il numero di porta su cui il server è in ascolto.
  • Metodo costruttore per ricevere un pacchetto:
public DatagramPacket(byte buffer[], int lunghezza)
  • Il server, per ricevere un messaggio, crea un oggetto DatagramPacket specificando la lunghezza massima del pacchetto.

Metodi per la gestione dell’indirizzo IP

  • Imposta l’indirizzo IP del destinatario:
void setAddress(InetAddress indirizzo)
  • Restituisce l’indirizzo IP dell’host da cui è partito il pacchetto:
InetAddress getAddress()

Metodi per gestire la porta

  • Imposta il numero della porta del destinatario:
void setPort(int port)
  • Restituisce la porta da cui è partito il pacchetto:
int getPort()

Metodi per gestire i dati

  • Imposta il contenuto del pacchetto:
void setData(byte buffer[])
  • Restituisce i dati contenuti nel pacchetto:
byte[] getData()

Capitolo 2: Implementazione di un’applicazione Client-Server UDP in Java

In questo capitolo realizzeremo un’applicazione Client-Server UDP, in cui più client possono connettersi al server tramite il protocollo UDP.
I client inviano delle stringhe di testo e il server le restituisce convertite in maiuscolo.


Implementazione del Server UDP

Descrizione del funzionamento del Server

  1. Creazione del socket:
    • Viene creato un oggetto DatagramSocket sulla porta 12345.
    • Si definiscono due buffer per i dati: uno per la ricezione e uno per la trasmissione (entrambi di 1024 byte).
    • Viene inizializzata una variabile booleana per gestire il ciclo di esecuzione del server.
  2. Attesa e ricezione dati dal Client:
    • Il server attende la ricezione di un pacchetto UDP tramite receive().
    • Il messaggio ricevuto viene estratto ed elaborato rimuovendo i caratteri superflui.
  3. Preparazione della risposta:
    • Il messaggio ricevuto viene convertito in maiuscolo.
    • Il server identifica l’indirizzo IP e la porta del client.
    • Viene creato un DatagramPacket contenente la risposta e inviato al client.
  4. Gestione dell’uscita:
    • Se il client invia "0", il server termina l’elaborazione, esce dal ciclo e chiude il socket.

Codice del Server (UDPServer.java)

import java.io.*;
import java.net.*;

public class UDPServer {
    public static void main(String[] args) {
        try {
            // Creazione del socket sulla porta 12345
            DatagramSocket UDPserver = new DatagramSocket(12345);
            DatagramPacket datagrammaRicevuto;
            DatagramPacket datagrammaDaInviare;
            boolean attivo = true;
            byte[] bufferIN = new byte[1024]; // Buffer per ricezione
            byte[] bufferOUT; // Buffer per invio

            System.out.println("Server avviato...");

            while(attivo){
                // Definizione del datagramma di ricezione
                datagrammaRicevuto = new DatagramPacket(bufferIN, bufferIN.length);
                UDPserver.receive(datagrammaRicevuto); // Attesa ricezione pacchetto

                // Estrazione del messaggio ricevuto
                String ricevuto = new String(datagrammaRicevuto.getData(), 0, datagrammaRicevuto.getLength());
                System.out.println("Messaggio ricevuto: " + ricevuto);

                // Riconoscimento parametri del client (IP e porta)
                InetAddress IPClient = datagrammaRicevuto.getAddress();
                int portaClient = datagrammaRicevuto.getPort();

                // Preparazione della risposta in maiuscolo
                String messaggioOUT = ricevuto.toUpperCase();
                bufferOUT = messaggioOUT.getBytes();
                datagrammaDaInviare = new DatagramPacket(bufferOUT, bufferOUT.length, IPClient, portaClient);

                // Invio del datagramma al client
                UDPserver.send(datagrammaDaInviare);

                // Se il client digita "0", termina l'esecuzione
                if (ricevuto.equals("0")){
                    System.out.println("Arrivederci...");
                    attivo = false;
                }
            }
            UDPserver.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Implementazione del Client UDP

Descrizione del funzionamento del Client

  1. Configurazione della comunicazione:
    • Vengono definiti i buffer per la comunicazione (trasmissione e ricezione).
    • Si specificano i riferimenti del server (indirizzo IP e porta 12345).
    • Viene creato un DatagramSocket per la comunicazione.
  2. Invio del messaggio al Server:
    • Il client chiede all’utente di inserire un messaggio.
    • Il messaggio viene convertito in array di byte e inviato al server tramite un DatagramPacket.
  3. Attesa e ricezione della risposta dal Server:
    • Il client si mette in attesa della risposta.
    • Una volta ricevuto il pacchetto, il messaggio viene estratto e stampato.
  4. Chiusura della connessione:
    • Dopo aver ricevuto la risposta, il client chiude il socket e termina l’esecuzione.

Codice del Client (UDPClient.java)

import java.io.*;
import java.net.*;

public class UDPClient {
    public static void main(String[] args) {
        try {
            int portaServer = 12345;
            InetAddress IPServer = InetAddress.getByName("localhost");
            byte[] bufferIN = new byte[1024]; // Buffer per ricezione
            byte[] bufferOUT; // Buffer per invio
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            DatagramSocket clientSocket;
            DatagramPacket datagrammaDaInviare;
            DatagramPacket datagrammaRicevuto;

            // Creazione del socket 
            clientSocket = new DatagramSocket();
            System.out.println("Inserisci una stringa: \n");

            // Lettura dell'input utente e preparazione buffer di uscita
            String messaggioDaInviare = input.readLine();
            bufferOUT = messaggioDaInviare.getBytes();

            // Creazione del DatagramPacket per l'invio
            datagrammaDaInviare = new DatagramPacket(bufferOUT, bufferOUT.length, IPServer, portaServer);
            clientSocket.send(datagrammaDaInviare);

            // Attesa della risposta dal server
            datagrammaRicevuto = new DatagramPacket(bufferIN, bufferIN.length);
            clientSocket.receive(datagrammaRicevuto);
            String ricevuto = new String(datagrammaRicevuto.getData());

            // Elaborazione del messaggio ricevuto
            int numCaratteri = datagrammaRicevuto.getLength();
            ricevuto = ricevuto.substring(0, numCaratteri);
            System.out.println("Messaggio ricevuto dal server: " + ricevuto);

            // Chiusura del socket
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Come eseguire il test con Visual Studio Code (VSC)

Per testare il funzionamento dell’applicazione Client-Server UDP su Visual Studio Code, segui questi passaggi:

  1. Apri Visual Studio Code.
  2. Apri la cartella in cui sono contenuti i file .java
  3. Manda in run il server
  4. Manda in run il client

Dovresti vedere il messaggio:

Server avviato...

Apri il Terminale di VSC e compila entrambi i file con il comando:

Se nel client invii “0”, il server mostrerà Arrivederci… e si chiuderà.

Nella sezione Download dedicata puoi scaricare i codici sorgente di applicazioni Applicazioni Client / Server con SOCKET UDP

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *