Una guida all'UDP in Java

1. Panoramica

In questo articolo, esploreremo la comunicazione di rete con Java, tramite lo User Datagram Protocol (UDP).

UDP è un protocollo di comunicazione che trasmette pacchetti indipendenti sulla rete senza alcuna garanzia di arrivo e nessuna garanzia dell'ordine di consegna .

La maggior parte delle comunicazioni su Internet avviene tramite il protocollo TCP (Transmission Control Protocol), tuttavia, UDP ha il suo posto che esploreremo nella prossima sezione.

2. Perché utilizzare UDP?

UDP è abbastanza diverso dal più comune TCP. Ma prima di considerare gli svantaggi a livello superficiale di UDP, è importante capire che la mancanza di overhead può renderlo significativamente più veloce di TCP.

Oltre alla velocità, dobbiamo anche ricordare che alcuni tipi di comunicazione non richiedono l'affidabilità del TCP, ma preferiscono una bassa latenza. Il video è un buon esempio di un'applicazione che potrebbe trarre vantaggio dall'esecuzione su UDP invece che su TCP.

3. Creazione di applicazioni UDP

La creazione di applicazioni UDP è molto simile alla creazione di un sistema TCP; l'unica differenza è che non stabiliamo una connessione punto a punto tra un client e un server.

Anche la configurazione è molto semplice. Java viene fornito con il supporto di rete integrato per UDP, che fa parte del pacchetto java.net . Pertanto per eseguire le operazioni di rete su UDP, abbiamo solo bisogno di importare le classi dalla java.net pacchetto: java.net.DatagramSocket e java.net.DatagramPacket .

Nelle sezioni seguenti, impareremo come progettare applicazioni che comunicano su UDP; useremo il popolare protocollo echo per questa applicazione.

Per prima cosa, costruiremo un server echo che rispedisce qualsiasi messaggio inviato, quindi un client echo che invia qualsiasi messaggio arbitrario al server e, infine, testeremo l'applicazione per assicurarci che tutto funzioni correttamente.

4. Il server

Nella comunicazione UDP, un singolo messaggio viene incapsulato in un DatagramPacket che viene inviato tramite un DatagramSocket .

Cominciamo impostando un semplice server:

public class EchoServer extends Thread { private DatagramSocket socket; private boolean running; private byte[] buf = new byte[256]; public EchoServer() { socket = new DatagramSocket(4445); } public void run() { running = true; while (running) { DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); InetAddress address = packet.getAddress(); int port = packet.getPort(); packet = new DatagramPacket(buf, buf.length, address, port); String received = new String(packet.getData(), 0, packet.getLength()); if (received.equals("end")) { running = false; continue; } socket.send(packet); } socket.close(); } }

Creiamo un DatagramSocket globale che useremo per inviare pacchetti, un array di byte per avvolgere i nostri messaggi e una variabile di stato chiamata running .

Per semplicità, il server sta estendendo Thread , quindi possiamo implementare tutto all'interno del metodo run .

All'interno di run , creiamo un ciclo while che viene eseguito fino a quando l' esecuzione viene modificata in false da qualche errore o da un messaggio di terminazione dal client.

Nella parte superiore del ciclo, creiamo un'istanza di DatagramPacket per ricevere i messaggi in arrivo.

Successivamente, chiamiamo il metodo di ricezione sul socket. Questo metodo si blocca finché non arriva un messaggio e memorizza il messaggio all'interno della matrice di byte del DatagramPacket passato a esso.

Dopo aver ricevuto il messaggio, recuperiamo l'indirizzo e la porta del client, poiché invieremo la risposta

indietro.

Successivamente, creiamo un DatagramPacket per inviare un messaggio al client. Notare la differenza di firma con il pacchetto di ricezione. Questo richiede anche l'indirizzo e la porta del client a cui stiamo inviando il messaggio.

5. Il cliente

Ora implementiamo un semplice client per questo nuovo server:

public class EchoClient { private DatagramSocket socket; private InetAddress address; private byte[] buf; public EchoClient() { socket = new DatagramSocket(); address = InetAddress.getByName("localhost"); } public String sendEcho(String msg) { buf = msg.getBytes(); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445); socket.send(packet); packet = new DatagramPacket(buf, buf.length); socket.receive(packet); String received = new String( packet.getData(), 0, packet.getLength()); return received; } public void close() { socket.close(); } }

Il codice non è molto diverso da quello del server. Abbiamo il nostro DatagramSocket globale e l'indirizzo del server. Istanziamo questi all'interno del costruttore.

Abbiamo un metodo separato che invia messaggi al server e restituisce la risposta.

Per prima cosa convertiamo il messaggio stringa in un array di byte, quindi creiamo un DatagramPacket per l'invio di messaggi.

Avanti: inviamo il messaggio. Convertiamo immediatamente il DatagramPacket in uno ricevente.

Quando arriva l'eco, convertiamo i byte in una stringa e restituiamo la stringa.

6. Il test

In una classe UDPTest.java , creiamo semplicemente un test per verificare la capacità di eco delle nostre due applicazioni:

public class UDPTest { EchoClient client; @Before public void setup(){ new EchoServer().start(); client = new EchoClient(); } @Test public void whenCanSendAndReceivePacket_thenCorrect() { String echo = client.sendEcho("hello server"); assertEquals("hello server", echo); echo = client.sendEcho("server is working"); assertFalse(echo.equals("hello server")); } @After public void tearDown() { client.sendEcho("end"); client.close(); } }

Nella configurazione , avviamo il server e creiamo anche il client. Mentre nel metodo tearDown , inviamo un messaggio di terminazione al server in modo che possa chiudersi e allo stesso tempo chiudiamo il client.

7. Conclusione

In questo articolo, abbiamo imparato a conoscere il protocollo datagramma utente e abbiamo creato con successo le nostre applicazioni client-server che comunicano su UDP.

Per ottenere il codice sorgente completo per gli esempi utilizzati in questo articolo, puoi controllare il progetto GitHub.