Introduzione al Networking in Java
Panoramica delle API di networking Java in java.net e java.net.http per connettersi a servizi remoti.
Il networking è il modo in cui un programma Java comunica con un altro programma — nella stessa stanza o dall'altra parte del mondo. Il JDK include uno stack completo per questo scopo in due pacchetti: il consolidato java.net (URL, socket, indirizzi) e il moderno java.net.http (l'HttpClient introdotto in Java 11). Questa parte del libro esplora quello stack dalle comodità di alto livello fino ai socket grezzi.
I livelli, dall'alto al basso
Le API di networking di Java formano una scala. Scegli il gradino più alto che soddisfa le esigenze:
| Gradino | API | Usala per |
|---|---|---|
| Più alto | HttpClient (java.net.http) | HTTP/HTTPS moderno: chiamate REST, download, async |
URL / URLConnection / HttpURLConnection | HTTP legacy e altri protocolli URL | |
Socket / ServerSocket | Protocolli TCP personalizzati, client/server propri | |
| Più basso | DatagramSocket | Messaggistica UDP senza connessione |
| Supporto | InetAddress | Risoluzione e rappresentazione di indirizzi IP |
La regola pratica: se stai chiamando un'API HTTP, usa HttpClient. Scendi ai socket solo quando stai usando un protocollo non-HTTP o stai costruendo un server personalizzato.
TCP vs. UDP
Due protocolli di trasporto stanno alla base di quasi tutto:
- TCP (
Socket,ServerSocket) è una connessione: affidabile, ordinata, basata su stream. I byte che scrivi arrivano integri e in ordine, oppure ricevi un errore. HTTP, database e la maggior parte dei protocolli applicativi si basano su TCP. - UDP (
DatagramSocket) è senza connessione: si inviano pacchetti indipendenti ("datagrammi") senza handshake, senza ordine e senza garanzia di consegna. Scambia affidabilità per bassa latenza — usato per DNS, streaming video e giochi.
Client vs. server
Un client avvia una connessione verso un indirizzo e una porta noti. Un server si lega a una porta e attende di accettare connessioni in arrivo. La stessa classe Socket rappresenta la connessione attiva su entrambi i lati; l'asimmetria riguarda solo chi avvia la conversazione. I capitoli successivi costruiscono entrambi i lati.
Bloccante per impostazione predefinita
Le classiche API java.net sono bloccanti: socket.getInputStream().read() sospende il thread chiamante finché non arrivano dati, e serverSocket.accept() sospende finché non si connette un client. Questo è semplice da ragionare ma significa un thread per connessione. (I canali java.nio e i thread virtuali affrontano la scalabilità; questa parte rimane sulle API bloccanti, che sono il punto di partenza corretto.)
Un esempio pratico: l'intero stack in un solo file
Per rendere concreti i pezzi, questo programma avvia un piccolo server HTTP sull'interfaccia di loopback, poi lo chiama con il moderno HttpClient — un ciclo client/server completo in una singola JVM, senza rete esterna richiesta.
Cosa ricavare dall'esecuzione:
- Un client e un server funzionanti stanno in un unico file breve. Le applicazioni reali li distribuiscono su macchine diverse, ma l'API è identica —
HttpServerha accettato una connessione eHttpClientne ha aperta una, incontrandosi su TCP sull'interfaccia di loopback (127.0.0.1). Questa è la forma di ogni programma di rete: un lato aspetta, uno chiama. - Il binding sulla porta 0 ha lasciato al sistema operativo la scelta di una porta libera, che
server.getAddress().getPort()ha restituito. Impostare una porta fissa rischia "indirizzo già in uso"; la porta 0 è il trucco standard per test e demo che hanno bisogno solo di una porta. - Il client non ha mai toccato un socket direttamente.
HttpClientha gestito la connessione, la riga di richiesta HTTP, le intestazioni e il parsing della risposta — questo è il valore di salire al gradino più alto della scala. I capitoli sui socket mostrano in seguito cosa ha nascosto. - La risposta conteneva metadati strutturati: un
statusCode()(200), unbody()e unaversion(). Le risposte HTTP sono più che testo; il client le ha modellate come un oggettoHttpResponsetipizzato in modo da leggere campi invece di analizzare uno stream. server.stop(0)ha rilasciato la porta. Le risorse di rete — socket, porte del server, connessioni — sono handle OS scarsi; ogni capitolo di questa parte li chiude esplicitamente (o con try-with-resources) in modo da non perderli.
Cosa tratta il resto di questa parte
I capitoli successivi scendono lungo la scala:
- La classe
URLeURLConnection/HttpURLConnection— analisi degli URL e API di connessione legacy. - Il moderno
HttpClientin profondità — richieste HTTP/2 sincrone e asincrone. - TCP grezzo con
SocketeServerSocket— costruire il proprio client e server. - UDP senza connessione con
DatagramSocket. - Risoluzione degli indirizzi con
InetAddress.
Il prossimo capitolo inizia dall'oggetto di networking più familiare di tutti: l'URL.