Home > java > Utilizzo dei Socket su protocolli UDP/IP

Utilizzo dei Socket su protocolli UDP/IP

5 giugno 2010

Translate in English with Google Translate
Introduzione
Le Socket rappresentano dei canali di comunicazione per permettere il flusso dei dati in reti basate su protocolli TCP/IP e UDP/IP. La scelta del protocollo da utilizzare dipende dall’uso richiesto. L’utilizzo del protocollo UDP viene richiesto nei casi in cui si devono trasferire delle ridotte quantità di informazioni e tra di esse non risulti nessun collegamento; si pensi allo scambio di messaggi tra applicativi che richiedono solo pochi byte. L’utilizzo del protocollo TCP, per svolgere il medesimo compito, richiederebbe un elevato numero di richieste di connessione ed il trasferimento di una quantità di informazioni di controllo paragonabili alla quantità di informazione utile da trasferire. Il linguaggio Java ci consente di utilizzare le Socket per il protocollo UDP in modo molto semplice, attraverso l’utilizzo di classi presenti nel package java.net.


Protocollo UDP
Il protocollo UDP fornisce un servizio di consegna di pacchetti non affidabile, non orientato alla connessione (connectionless transport protocol).
Il protocollo UDP non è affidabile perché:

  • non garantisce la consegna dei pacchetti;
  • può evitare di eseguire i controlli sull’integrità dei dati trasmessi attraverso i calcoli di checksum;
  • non garantisce l’ordinata consegna dei dati;
  • non invia messaggi sull’esito della trasmissione, pertanto dei datagrammi possono andare perduti o possono essere duplicati. Il controllo è totalmente applicativo.

Il protocollo UDP non è orientato alla connessione in quanto non viene realizzata nessuna connessione tra i due host , ma i datagrammi vengono trattati singolarmente.

  • I vantaggi del protocollo sono dati dalla velocità nel trasferimento dei dati grazie alla mancanza di controlli per l’instradamento, il supporto delle comunicazione point to point(PTP) e point to multipoint (PTM) . Questo significa che è possibile inviare i datagrammi verso un unico destinatario (PTP) o verso molti destinatari (PTM). Al Livello Network un messaggio viene suddiviso in pacchetti per essere inviato. Il pacchetto, in un servizio senza connessione (connectionless), viene denominato datagramma (datagrams).
  • Gli svantaggi sono dovuti all‘incertezza nel trasferimento dei dati, a causa delle mancanza di garanzie offerte nella trasmissione. In presenza di rete congestionata aumentano le incertezze sul corretto instradamento dei pacchetti.

Esempi di protocolli UDP utilizzati: DNS – SNMP –TFTP –NFS .

Testata UDP
La IAB (Internet Architecture Board) è un’organizzazione commissionata dalla IETF (Internet Engineering Task Force) che si occupa di redarre e pubblicare i documenti RFC (Request for Comments) e gli articoli che trattano di argomenti relativi ai protocolli TCP/IP e alla rete Internet. Tali documenti seguono la dicitura RFC seguita da un numero progressivo. Per cercare dei documenti RFC è possibile cliccare qui e indicare il numero progressivo del documento cercato.
La descrizione completa del protocollo UDP è contenuta nel documento RFC768. Di seguito viene riportata la testata del protocollo UDP. Essa è relativamente semplice.

User Datagram Header Format

User Datagram Header Format

  • I campi Source Port e Destination Port identificano la sorgente e la destinazione del pacchetto
  • Il campo Length indica la lunghezza dell’intero datagramma UDP (testata + dati) in byte. Il valore minimo è 8, ma in realtà questo campo non viene gestito dal protocollo, che sa che la lunghezza totale è la lunghezza di un datagramma IP meno i 20 byte della testata IP.
  • Il campo Checksum è anch’ esso opzionale ed è calcolato dal mittente e verificato dal ricevitore del pacchetto. Se il pacchetto UDP è errato, viene scartato senza generazione di messaggi d’errore.

Ogni operazione di output di un processo che usa il trasporto UDP produce esattamente un datagramma UDP, che viene incapsulato in un pacchetto IP. La lunghezza della testata è di 8 byte.

Porte
I servizi attivati su protocollo UDP sono raggiungibili su determinate porte. Alcune di queste porte sono stabilita dalla IANA ( Internet Assigned Numbers Authority ), mentre altre porte sono customizzate.

Socket sul protocollo UDP
In Java le Socket sono implementate con classi distinte a seconda che si intenda utilizzarle sul protocollo TCP o UDP
Per il protocollo UDP vengono utilizzate le classi:

  • DatagramSocket : socket UDP semplici
  • MulticastSocket : socket UDP multicast.

Creazione del Server UDP
Per realizzare una comunicazione client/server avvalendosi dei socket UDP occorre creare un server UDP in ascolto su una determinata porta ed un client che effettui una chiamata.
Per creare un server in ascolto occorre seguire alcuni passaggi:

  1. Importare i package java.io, java.net per poter utilizzare le classi relative alle Socket.
  2. Intercettare l’eccezione IOException, che deve essere gestita o propagata poiché vengono richiamati dei metodi delle classi appartenenti ai package java.io e java.net.
  3. Creare un oggetto DatagramSocket utilizzando il costruttore DatagramSocket (int port) che accetta come parametro la porta del Server in ascolto per il servizio da attivare. In questo esempio è stata utilizzata la porta 7777.
  4. DatagramSocket s = new DatagramSocket(7777);
    
  5. Creare un oggetto DatagramPacket che ci consenta di poter leggere (in questo caso) i dati dal client come un array di byte. Il Costruttore accetta come parametri, oltre all’array di byte e la sua lunghezza, anche l’indirizzo e la porta attivata del client.
  6. DatagramPacket(byte[] buf, int length)
    DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    
  7. Richiamare il metodo receive() sull’oggetto DatagramSocket: in questo modo è possibile ricevere da parte del client il pacchetto contenuto nell’oggetto DatagramPacket .
  8. public void receive(DatagramPacket p)
    

    Il pacchetto ricevuto conterrà i dati, strutturati in un array di byte, che possono essere ricavati utilizzando il metodo getData() dell’oggetto DatagramPacket e potranno essere convertiti in una stringa per la stampa.

    byte[] getData()

Da questo esempio notiamo che, mentre il protocollo TCP apre, usa e chiude connessioni (socket) ad una
certa porta, il protocollo UDP spedisce datagrammi contenenti l’identificativo della porta.
Esso viene spedito seguendo un percorso indipendentemente dagli altri datagrammi. Ciascun datagramma,
infatti, segue le strade stabilite dai router e queste possono cambiare in ogni momento per evitare per
esempio router non più attivi o congestioni di rete.

La classe DatagramSocket dispone inoltre di metodi utilizzati per l’apertura e la chiusura del socket:

void connect(InetAddress address, int port)
void disconnect()

Esempio di un semplice server UDP

//Importo i package necessari
import java.net.*;
import java.io.*;
public class ServerUDP {
   public void start() throws IOException {

     //Attivo la Socket sul Server in ascolto sulla porta 7777
     DatagramSocket s = new DatagramSocket(7777);

     //Informazioni sul Server in ascolto
     InetAddress indirizzo = s.getLocalAddress();
     String server = indirizzo.getHostAddress();
     int port = s.getLocalPort();
     System.out.println("In ascolto Server UDP: "+ server + " porta: " + port);

     //Ciclo infinito per ascolto dei Client
     while (true) {

       //Preparazione delle informazioni da ricevere
       byte[] buf = new byte[65536];
       System.out.println("In attesa di chiamate dai Client... ");
       DatagramPacket recv = new DatagramPacket(buf, buf.length);
       s.receive(recv);

       //Informazioni sul Client che ha effettuato la chiamata
       InetAddress address = recv.getAddress();
       String client = address.getHostName();
       int porta = recv.getPort();
       System.out.println("In chiamata Client: "+ client + " porta: " + porta);

       //Messaggio ricevuto dal Client
       String messaggio = (new String(recv.getData()).trim());
       System.out.println("Il Client ha scritto: " + messaggio);
     }
   }
   public static void main (String[] args) throws IOException {
     ServerUDP udpServer = new ServerUDP();
     udpServer.start();
   }
}

Creazione del Client UDP
Per creare un Client UDP che effettui una chiamata ad un Server UDP occorre seguire questi passaggi:

  1. Importare i package java.io, java.net per poter utilizzare le classi relative alle Socket.
  2. Intercettare l’eccezione IOException, che deve essere gestita o propagata, poiché vengono richiamati dei metodi delle classi appartenenti ai package java.io e java.net che sollevano questa eccezione.
  3. Creare un oggetto DatagramSocket per attivare la porta del Socket sul Client. E’ anche possibile non specificare la porta in quanto si può usare un costruttore vuoto che ne prenderà una disponibile.
  4. DatagramSocket()
    DatagramSocket(int port)
  5. Creare un oggetto DatagramPacket per indicare l’ array di byte da utilizzare, la sua lunghezza, l’indirizzo e la porta del server.
  6. DatagramPacket(byte[] buf, int length)
    DatagramPacket(byte[] buf, int length, InetAddress address, int port)
  7. Inviare il pacchetto cosi creato sulla Socket del datagramma attraverso il metodo send() dell’oggetto DatagramSocket.
  8. void send(DatagramPacket p)

Esempio di un semplice Client UDP

//Importo i package necessari
import java.net.*;
import java.io.*;

public class ClientUDP {
    public void avvio() throws IOException {
       InetAddress addr = InetAddress.getByName("localhost");
       BufferedReader stdIn= new BufferedReader(new InputStreamReader(System.in));
       byte [] msg = {0};

       //Creazione della Socket per l'invio del Datagramma con porta Client dinamica
       DatagramSocket s = new DatagramSocket();

       //Creazione del pacchetto da inviare al Server
       DatagramPacket hi = new DatagramPacket(msg, msg.length, addr, 7777);

       //Ciclo infinito per inserimento testo del Client
       while (true) {
         System.out.print("Inserisci: ");
         String userInput = stdIn.readLine();
         System.out.println("userInput: " + userInput);
         msg = userInput.getBytes();
         hi.setData(msg);
         hi.setLength(msg.length);

         //Invio del pacchetto sul Socket
         s.send(hi);
       }
    }
    public static void main (String[] args) throws IOException {
       ClientUDP udpClient = new ClientUDP();
       udpClient.avvio();
    }
}

Conclusioni
Il protocollo UDP è il più semplice meccanismo di comunicazione fra elaboratori, in quanto permette un interscambio di dati. Questo protocollo fornisce ai programmi applicativi un semplice meccanismo per scambiare messaggi, utilizzando il minimo indispensabile di informazione supplementare. Non offre le stesse garanzie del protocollo TCP, ma risulta molto utile in tutti quei casi in cui lo scambio delle informazioni è molto ridotto. La scelta del protocollo di comunicazione dipende sempre dall’uso che bisogna farne. Non esiste un protocollo adatto da usare in qualunque circostanza.

Categorie:java
  1. Gigi
    16 ottobre 2013 alle 4:42 PM

    Salve volevo fare una domanda, se si volesse utilizzare il protocollo UDP per scambiare dei numeri come bisognerebbe fare?Sto provando a fare la somma di due numeri sul server, passati dal client ma mi restituisce numeri strani

    • 17 ottobre 2013 alle 2:34 PM

      Dovrei vedere il tuo codice per capire meglio ma nel frattempo ho creato un metodo sul ServerUDP da invocare prima della chiusura del ciclo while, del tipo: somma(messaggio); in questo caso occorre passare solo dei numeri ed il server fa la somma:

      class ServerUDP {
      ...
      private void somma(String messaggio){
             long somma = 0;
             messaggio = messaggio.replaceAll("( )+", " ").trim();
             for (String numero : messaggio.split(" ") ){
                 somma += Long.parseLong(numero);
             }
             System.out.println("La somma di " + messaggio + " = " + somma);
         }
      }
      

      In sede di esecuzione, a fronte dell’inserimento di 2 numeri: 12 34 otterrai:

      Il Client ha scritto: 12 34
      La somma di 12 34 = 46
      
  1. No trackbacks yet.
I commenti sono chiusi.
%d blogger cliccano Mi Piace per questo: