Java Networking – Einführung
Überblick über die Java-Networking-APIs in java.net und java.net.http zum Verbinden mit entfernten Diensten.
Networking beschreibt, wie ein Java-Programm mit einem anderen Programm kommuniziert – im selben Raum oder auf der anderen Seite der Welt. Das JDK liefert dafür einen vollständigen, sofort einsatzbereiten Stack in zwei Paketen: das altbewährte java.net (URLs, Sockets, Adressen) und das moderne java.net.http (der in Java 11 eingeführte HttpClient). Dieser Teil des Buches führt durch diesen Stack – von den komfortablen High-Level-APIs bis hin zu rohen Sockets.
Die Schichten – von oben nach unten
Javas Networking-APIs bilden eine Leiter. Wähle die höchste Sprosse, die die Aufgabe erfüllt:
| Sprosse | API | Verwendung |
|---|---|---|
| Höchste | HttpClient (java.net.http) | Modernes HTTP/HTTPS: REST-Aufrufe, Downloads, async |
URL / URLConnection / HttpURLConnection | Legacy-HTTP und andere URL-Protokolle | |
Socket / ServerSocket | Eigene TCP-Protokolle, eigener Client/Server | |
| Niedrigste | DatagramSocket | Verbindungsloses UDP-Messaging |
| Unterstützung | InetAddress | Auflösung und Darstellung von IP-Adressen |
Die Faustregel lautet: Wenn du eine HTTP-API aufrufen möchtest, nutze HttpClient. Wechsle zu Sockets nur dann, wenn du ein Nicht-HTTP-Protokoll verwendest oder einen eigenen Server baust.
TCP vs. UDP
Zwei Transportprotokolle bilden die Grundlage für fast alles:
- TCP (
Socket,ServerSocket) ist eine Verbindung: zuverlässig, geordnet, streambasiert. Bytes, die du schreibst, kommen vollständig und in der richtigen Reihenfolge an – oder du erhältst einen Fehler. HTTP, Datenbanken und die meisten Anwendungsprotokolle nutzen TCP. - UDP (
DatagramSocket) ist verbindungslos: Du sendest unabhängige Pakete ("Datagramme") ohne Handshake, ohne Reihenfolge und ohne Zustellungsgarantie. Es tauscht Zuverlässigkeit gegen niedrige Latenz – verwendet für DNS, Video-Streaming und Spiele.
Client vs. Server
Ein Client initiiert eine Verbindung zu einer bekannten Adresse und einem bekannten Port. Ein Server bindet sich an einen Port und wartet darauf, eingehende Verbindungen zu akzeptieren. Dieselbe Socket-Klasse repräsentiert die aktive Verbindung auf beiden Seiten; die Asymmetrie liegt nur darin, wer das Gespräch beginnt. Spätere Kapitel bauen beide Seiten auf.
Blockierend als Standard
Die klassischen java.net-APIs sind blockierend: socket.getInputStream().read() hält den aufrufenden Thread an, bis Daten eintreffen, und serverSocket.accept() hält an, bis ein Client sich verbindet. Das ist einfach zu verstehen, bedeutet aber einen Thread pro Verbindung. (java.nio-Channels und virtuelle Threads adressieren die Skalierung; dieser Teil bleibt bei den blockierenden APIs, die der richtige Einstiegspunkt sind.)
Ein durchgearbeitetes Beispiel: Der gesamte Stack in einer Datei
Um die Teile greifbar zu machen, startet dieses Programm einen kleinen HTTP-Server auf dem Loopback-Interface und ruft ihn dann mit dem modernen HttpClient auf – ein vollständiger Client/Server-Roundtrip in einer einzigen JVM, ohne externes Netzwerk.
Was aus dem Lauf mitgenommen werden sollte:
- Ein funktionierender Client und Server passen in eine kurze Datei. Echte Anwendungen verteilen sie über Maschinen, aber die API ist identisch –
HttpServerhat eine Verbindung akzeptiert undHttpClienthat eine geöffnet, die sich über TCP auf dem Loopback-Interface (127.0.0.1) trafen. Das ist die Form jedes vernetzten Programms: eine Seite wartet, eine Seite ruft an. - Die Bindung an Port 0 ließ das Betriebssystem einen freien Port auswählen, den
server.getAddress().getPort()zurückgemeldet hat. Das Hardcodieren eines Ports birgt das Risiko von "Adresse bereits in Verwendung"; Port 0 ist der Standardtrick für Tests und Demos, die nur irgendein Port benötigen. - Der Client hat nie direkt einen Socket berührt.
HttpClienthat die Verbindung, die HTTP-Anforderungszeile, die Header und das Parsen der Antwort übernommen – das ist der Wert, die höchste Sprosse der Leiter zu erklimmen. Die Socket-Kapitel zeigen später, was dabei verborgen blieb. - Die Antwort enthielt strukturierte Metadaten: einen
statusCode()(200), einenbody()und eineversion(). HTTP-Antworten sind mehr als Text; der Client modellierte sie als typisiertesHttpResponse-Objekt, sodass du Felder liest statt einen Stream zu parsen. server.stop(0)hat den Port freigegeben. Netzwerkressourcen – Sockets, Server-Ports, Verbindungen – sind knappe Betriebssystem-Handles; jedes Kapitel in diesem Teil schließt sie explizit (oder mit try-with-resources), damit sie nicht verloren gehen.
Was der Rest dieses Teils behandelt
Die kommenden Kapitel gehen die Leiter hinunter:
- Die
URL-Klasse undURLConnection/HttpURLConnection– URLs parsen und die Legacy-Verbindungs-API. - Der moderne
HttpClientin der Tiefe – synchrone und asynchrone HTTP/2-Anfragen. - Rohes TCP mit
SocketundServerSocket– einen eigenen Client und Server bauen. - Verbindungsloses UDP mit
DatagramSocket. - Adressauflösung mit
InetAddress.
Das nächste Kapitel beginnt mit dem vertrautesten Networking-Objekt von allen: der URL.