Das Web-Protokoll: HttpURLConnection unter Java
Willemers Informatik-Ecke
Die Programmierung einer TCP/IP-Verbindung kann über Sockets erfolgen. Eines der wichtigsten Anwendungsprotokolle ist das Web-Protokoll HTTP. Wenn man eine Kommunikation über HTTP einrichten will, bietet Java die Klasse HttpURLConnection nutzen. Sie hat den Charme, dass sie ohne zusätzliche Bibliothek verfügbar ist, beispielsweise auch unter Android.

Klasse und Methoden

Die Klasse HttpURLConnection erweitert die abstrakte Klasse URLConnection.

Daten lesen

Über die URLConnection-Methode getInputStream kann ein Datenstrom geholt werden, der wiederum über die Methode read in ein byte-Array ausgelesen werden kann.

Das Auslesen der Pakete aus byte-Arrays ist allerdings mühsam. Darum lohnt es sich einen InputStreamReader zu erzeugen, der den InputStream der Verbindung als Konstruktorparameter übergibt. Damit lassen sich char-Arrays auslesen.

Um an einen String zu gelangen, wird BufferedReader erzeugt, der wiederum den InputStreamReader als Konstruktorparameter verwendet. Daraus lässt sich nun per readLine zeilenweise je ein String auslesen.

// InputStream aus Verbindung http bauen
InputStream inStream = http.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
String empfangeneZeile = in.readLine();

Ist der empfangene String gleich null, ist das Datenende erreicht.

Daten schreiben

Das Schreiben funktioniert umgekehrt zum Lesen. Zuerst muss allerdings die Ausgabe durch den Aufruf von setDoOutput(true) freigeschaltet werden.

  1. Über die URLConnection-Methode getOutputStream erlangt man einen OutPutStream.
  2. Dieser wird als Parameter dem Konstruktor von einem OutputStreamWriter übergeben.
  3. Der OutputStreamWriter wird wiederum der Konstruktorparameter eines PrintWriter-Objekts.
  4. Dieses bietet die Methode print an.

Auslesen einer URL mit GET

Das folgende Beispielprogramm liest eine URL per HTTP mit dem Mode GET aus und gibt den HTML-Code auf dem Bildschirm aus.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpClient {
    static public void doGet(String url) {
        try {
            HttpURLConnection http = (HttpURLConnection)
                    new URL(url).openConnection();
            http.setRequestProperty("Accept-Charset", "UTF-8");
            http.setRequestMethod("GET");
            // InputStream aus Verbindung bauen
            InputStream inStream = http.getInputStream();
            // Input-Stream könnte per read in ein Array gelesen
            // werden. Eleganter ist allerdings ein BufferedReader
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(inStream));
            // In antwort werden die eingelesenen Zeilen gesammelt
            StringBuffer antwort = new StringBuffer();
            String empfangeneZeile; // für jede Zeile
            // Lese zeilenweise ..,
            while ((empfangeneZeile = in.readLine()) != null) {
                antwort.append(empfangeneZeile + "\n");
            }
            in.close(); // Stream schließen und damit die Verbindung
            System.out.println(antwort.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        doGet("http://www.willemer.de/informatik");
    }
}

Senden von Daten per POST

Die Methode POST wird in erster Linie für das Senden von HTML-FORMs verwendet. Mit dem folgenden Programm werden wir dies in einem Java-Programm nachahmen. Die Methode doPost erhält als einen Parameter die URL des auswertenden Programms und als zweiten Parameter den Formularinhalt in der Form, wie ihn auch eine HTML-Seite senden würde.

Vor dem Senden wird die Methode auf POST gestellt und mit setDoOutput(true) das Senden ermöglicht. Dazu wird ein DataOutputStream über die Verbindung gebaut. Dessen Methode write sorgt dann für das Versenden.

Im nächsten Schritt wird der Reader für die Verbindung erstellt, über den mit der Methode readLine das Ergebnis zeilenweise gelesen wird.

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class HttpPostClient {

    static void doPost(String url, String urlParameters)
                throws MalformedURLException, IOException {
        HttpURLConnection http = (HttpURLConnection)
                new URL(url).openConnection();
        // Methode auf POST, Output ermöglichen
        http.setRequestMethod("POST");
        http.setDoOutput(true);
        // Zeigensatz UTF-8 und FORM-Ausgabe anmelden
        http.setRequestProperty("charset", "utf-8");
        http.setRequestProperty("Content-Type",
                                "application/x-www-form-urlencoded");
        byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
        http.setRequestProperty("Content-Length"
                                Integer.toString(postData.length));
        // Die übergebenen Daten an Server senden
        DataOutputStream wr = new DataOutputStream(http.getOutputStream());
        wr.write(postData);
        // Ergebnisse abholen - wie bei GET
        // InputStream aus Verbindung bauen
        InputStream inStream = http.getInputStream();
        // Input-Stream könnte per read in ein Array gelesen
        // werden. Eleganter ist allerdings ein BufferedReader
        BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
        // In antwort werden die eingelesenen Zeilen gesammelt
        StringBuffer antwort = new StringBuffer();
        String empfangeneZeile; // für jede Zeile
        // Lese zeilenweise ..,
        while ((empfangeneZeile = in.readLine()) != null) {
            antwort.append(empfangeneZeile + "\n");
        }
        in.close(); // Stream schließen und damit die Verbindung
        System.out.println(antwort.toString());        
    }

    public static void main(String[] args)
                throws MalformedURLException, IOException {
        doPost("http://localhost/post.php",
               "name=Arnold&zahl=21&land=SH");
    }
}

Links