1. Netzwerkprogrammierung
Zugriffe auf das Netzwerk sind heute so üblich wie der Zugriff auf das lokale Dateisystem. Seit Java 1.0 bietet Java eine Netzwerk-API zum Entwickeln von Client-Server-Anwendungen. Die Java-Bibliothek kann verschlüsselte Verbindungen aufbauen und bringt ebenso Unterstützung für das Hypertext Transfer Protocol (HTTP) mit. Bei den Aufgaben in diesem Kapitel geht es um das Beziehen von Ressourcen von einem Web-Server und das Entwickeln einer kleinen Client-Server-Anwendung mit eigenem Protokoll.
Voraussetzungen
URL
-Klasse kennenDatenströme beherrschen
Internetressourcen auslesen können
Client und Server mit
Socket
undServerSocket
implementieren können
Verwendete Datentypen in diesem Kapitel:
Noch mehr Aufgaben findest du im Buch: ›Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java. 300 Java-Workshops, Aufgaben und Übungen mit kommentierten Lösungen‹
1.1. URL und URLConnection
In Java repräsentiert die naheliegende Klasse URL
eine URL und URI
eine URI. Über URL
lässt sich eine HTTP-Verbindung öffnen, intern übernimmt das der Vermittler URLConnection
.
Beide Klassen sind für moderne HTTP-Aufrufe nicht komfortabel; erst in Java 11 ist ein neues Paket java.net.http
dazugekommen mit dem HttpClient
im Mittelpunkt. Java-Enterprise-Frameworks haben weitere Lösungen, und im Open-Source-Universum gibt es ebenfalls viele Alternativen:
Client-API in Jakarta EE
WebClient
in Spring WebfluxOkHttp
Apache HttpClient
Feign und Retrofit
1.1.1. Entfernte Bilder über die URL herunterladen ⭐
Die URL
-Klasse bietet eine Methode, die einen InputStream
liefert, sodass sich die Bytes der Ressource auslesen lassen.
Captain CiaoCiao entspannt sich gerne mit Bildern von wohl geformten Schiffen auf shiphub.com. Er hätte gerne einige Bilder auf seinem Speichermedium, sodass er auf langen Reisen etwas zum Träumen hat.
Aufgabe:
Schreibe ein Programm, das bei einer gegeben URL die Ressource herunterlädt und auf dem lokalen Dateisystem speichert.
Der Dateiname soll an die URL angelehnt sein.
1.1.2. Entfernte Textdatei über die URL einlesen ⭐
Das Center for Systems Science and Engineering (CSSE) der Johns Hopkins University veröffentlicht unter https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports jeden Tag eine CSV-Datei mit Daten über Covid-Erkrankungen auf der ganzen Welt. Für den 1. März 2021 lautet die URL auf dem Server: https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/03-01-2021.csv.
Die Datei beginnt mit
FIPS,Admin2,Province_State,Country_Region,Last_Update,Lat,Long_,Confirmed,Deaths,Recovered,Active,Combined_Key,Incidence_Rate,Case-Fatality_Ratio ,,,Afghanistan,2020-10-22 04:24:27,33.93911,67.709953,40510,1501,33824,5185,Afghanistan,104.06300129769207,3.7052579609972844 ,,,Albania,2020-10-22 04:24:27,41.1533,20.1683,17948,462,10341,7145,Albania,623.6708596844812,2.574102964118565 ,,,Algeria,2020-10-22 04:24:27,28.0339,1.6596,55081,1880,38482,14719,Algeria,125.60932701190256,3.4131551714747372
Aufgabe:
Lege eine neue Klasse
CoronaData
mit einer neuen MethodeString findByDateAndSearchTerm(LocalDate date, String search)
an.findByDateAndSearchTerm(…)
soll mit dem Datum einURL
-Objekt aufbauen. Bedenke, dass der Dateiname die Reihenfolge Monat, Tag, Jahr hat.Öffne einen Datenstrom zur generierten URL, lese den Strom zeilenweise ein, und filtere alle Zeilen heraus, die nicht den übergebenen Teil-String
search
beinhalten.Am Ende entsteht ein String mit allen Zeilen mit dem Suchwort, ein CSV-Parser ist nicht nötig.
Beispiel:
Der Aufruf
findByDateAndSearchTerm( LocalDate.now().minusDays( 1 ), "Miguel" )
liefert aus dem entfernten CSV-Dokument alle Corona-Zahlen von gestern, die"Miguel"
enthalten.Beispielhafte Rückgabe:
8113,San Miguel,Colorado,US,2020-10-22 04:24:27,38.00450883,-108.4020725,100,0,0,100,"San Miguel, Colorado, US",1222.643354933366,0.0 35047,San Miguel,New Mexico,US,2020-10-22 04:24:27,35.48014807,-104.8163562,151,0,0,151,"San Miguel, New Mexico, US",553.5799391428677,0.0
Wenn die CORONA-Zahlen zurückgehen es ist gut möglich, dass die CSSE keine neuen Dokumente mehr veröffentlicht. Die alten Dokumente sollten bleiben. |
1.2. HTTP-Client
Zwar lässt sich mit URLConnection
prinzipiell eine HTTP-Anfrage stellen, die HTTP-Methode (GET, POST, PUT …) ändern und Header setzen, doch komfortabel ist das nicht. Daher wurde in Java 11 der HTTP-Client hinzugefügt. Mit der neuen API lassen sich HTTP-Ressourcen eleganter über das Netzwerk anfordern. Außerdem unterstützt der HTTP-Client HTTP/1.1 und HTTP/2 sowie synchrone als auch asynchrone Programmiermodelle. Mit dieser API wollen wir die Aufgaben lösen; wer kein Java 11 nutzen kann, findet mit dem https://github.com/AsyncHttpClient/async-http-client eine ähnliche Bibliothek für Java 8. Auch im nächsten Kapitel zu den Dateiformaten kommen wir in den Aufgaben noch einmal auf den HTTP-Client zurück, da oftmals JSON oder XML ausgetauscht werden.
1.2.1. Top-News von Hacker News ⭐⭐
Hacker News ist eine Website mit aktuell diskutieren Technologietrends. Die Beiträge lassen sich über einen Webservice abrufen, die Dokumentation findet sich unter https://github.com/HackerNews/API. Zwei Endpunkte sind:
https://hacker-news.firebaseio.com/v0/topstories.json: liefert ein JSON-Array mit IDs der meist-diskutierten Artikel
https://hacker-news.firebaseio.com/v0/item/24857356.json: liefert ein JSON-Objekt mit der Nachricht mit der ID
24857356
Aufgabe:
Lege eine neue Klasse
HackerNews
an.Implementiere eine neue Methode
long[] hackerNewsTopStories()
, diemit dem HTTP-Client eine Verbindung zum Endpunkt https://hacker-news.firebaseio.com/v0/topstories.json aufbaut,
die Rückgabe aus dem JSON in long zerlegt,
alle IDs als
long[]
zurückgibt.Im Falle eines IO-Fehlers soll ein leeres Array zurückgegeben werden.
Implementiere eine neue Methode
String news(long id)
, die als String das komplette JSON-Dokument liefert.
Beispiel:
Die Klasse mit den beiden Methoden kann so genutzt werden:
System.out.println( Arrays.toString( hackerNewsTopStories() ) ); String newsInJson = news( 24857356 ); System.out.println( newsInJson );
1.3. Socket und ServerSocket
Betriebssysteme bieten Sockets zur TCP/UDP-Kommunikation; sie kann Java über die Klassen
java.net.Socket
undjava.net.ServerSocket
für TCP undjava.net.DatagramSocket
für UDP nutzen.
Erzeugt werden Objekte von Socket
und ServerSocket
über den Konstruktor oder noch besser über die Fabriken javax.net.SocketFactory
und javax.net.ServerSocketFactory
; für UDP gibt es keine Fabrik.
1.3.1. Einen Schimpfserver implementieren und den Client dazu ⭐⭐
Bonny Brain nimmt bald am nächsten Schimpf-Wettbewerb teil. Sie möchte sich perfekt vorbereiten. Auf einem Server soll eine Anwendung laufen, die Sprüche verwaltet und Clients können sich zu diesem Schimpfserver verbinden und nach Sprüchen suchen.
Aufgabe:
Schreibe einen Server und Client.
Passe den Server so an, dass er mehrere Verbindungen annehmen kann; greife auf einen Thread-Pool zurück.
Der Thread-Pool soll eine maximale Anzahl von Threads nutzen, um Denial-of-Service-Attacken (DOS) einzudämmen. Ist die maximale Anzahl gleichzeitiger Verbindungen erschöpft, muss ein Client warten, bis wieder eine Verbindung frei wird.
Beispiel:
Nach dem Starten des Servers und des Clients kann eine Interaktion so aussehen:
sir You, sir, are an oxygen thief! an You, sir, are an oxygen thief! Stop trying to be a smart ass, you're just an ass.
1.3.2. Einen Port-Scanner implementieren ⭐⭐
Bonny Brain installiert das neue Ay! OS, doch wichtige Analysewerkzeuge fehlen. Sie benötigt ein Werkzeug, das die belegten TCP/UDP-Ports erkennt und meldet.
Aufgabe:
Schreibe ein Programm, das versucht, auf allen TCP/UDP-Ports von 0 bis 49151 einen
ServerSocket
undDatagramSocket
zu registrieren; wenn das gelingt, ist der Port frei, andernfalls besetzt.Zeige die belegten Ports auf der Konsole an und dazu für die bekannten Ports eine Beschreibung des üblichen Dienstes, der diesen Port einnimmt.
Beispiel:
Die Ausgabe könnte so aussehen:
Protocol Port Service TCP 135 EPMAP UPD 137 NetBIOS Name Service UPD 138 NetBIOS Datagram Service TCP 139 NetBIOS Session Service TCP 445 Microsoft-DS Active Directory TCP 843 Adobe Flash UPD 1900 Simple Service Discovery Protocol (SSDP) UPD 3702 Web Services Dynamic Discovery TCP 5040 UPD 5050 UPD 5353 Multicast DNS UPD 5355 Link-Local Multicast Name Resolution (LLMNR) TCP 5939 TCP 6463 TCP 6942 TCP 17500 Dropbox UPD 17500 Dropbox TCP 17600 TCP 27017 MongoDB UPD 42420
Eine Netzwerkschnittstelle (engl. network interface) verbindet Computer über ein Rechnernetz. Im Folgenden gehen wir immer von einer TCP/UDP Schnittstelle aus. Die Netzwerkschnittstelle muss nicht physikalisch sein, sondern kann auch in Software implementiert werden. Wie die Loopback-Schnittstelle mit der IP Zur Registrierung eines Server-Sockets gibt es zwei Möglichkeiten: entweder akzeptiert der Dienst nur Anfragen von einer speziellen lokalen Die Lösung der Aufgabe kann einen einfachen Test durchführen und den Socket-Socket auf allen Netzwerkschnittstellen registrieren; scheitert das, war auf einer der Netzwerkschnittstellen schon ein Dienst aktiv. Das reicht für uns als Kriterium, dass auf irgendeiner Netzwerkschnittstelle der Port belegt ist. |
Noch mehr Aufgaben findest du im Buch: ›Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java. 300 Java-Workshops, Aufgaben und Übungen mit kommentierten Lösungen‹