Advanced
Java
Services
|
URL's und die Klasse URL |
Ein URL (uniform resource locator) ist eine Internetadresse, die man etwa in einen Browser eingibt.
Die Adresse enthält den Namen eines Serverrechners (host) und einer Datei auf dem Server, die der
Browser dann versucht zu laden. Zusätzlich muß man angeben, nach welchem Protokoll der Datenaustausch
zwischen Server und Client erfolgen soll. Eine jede solche Verbindung wird über einen sogenannten
Port abgewickelt. Vergleicht man den Server mit einem Bahnhof, so spielt ein Port die Rolle eines
Bahnsteigs. Für die wichtigsten Protokolle gibt es Defaultports, die jeder Browser kennt und
die man daher nicht angeben muß. Hinter dem Dateinamen kann ein Verweis auf eine bestimmte Stelle
in dieser Datei stehen. Nach dem Dateinamen, bzw. nach der Stellenangabe in einer Datei kann der
Browser nach einem Fragezeichen zusätzlich noch Daten an den Server schicken. Das Fragezeichen ist
dabei das Trennzeichen, das die Dateiidentifizierung von den Daten trennt.
Allgemeiner Aufbau eines URL
Die Angaben bis einschließlich des Dateinamens sind obligatorisch, die Angaben nach dem
Kreuzzeichen (#) können auch fehlen. Gibt man unvollständige Adressen ein, so ergänzt der
Browser die unvollständige Adresse nach seinen Defaultvorgaben. Fehlt die Protokollangabe, so wird
normalerweise http angenommen. Zu einem Protokoll wird dann der jeweilige Defaultport ergänzt.
Beispiele
Alle obenstehenden Kurzformen werden ergänzt zu :
http://www.straub.as:80/index.html
Einige wichtige Protokolle und ihre Ports
Protokollname | Port | Protokollart | Beschreibung
echo
| 7
| TCP/UDP
| Protokoll zum Aufbau einer Testverbindung.
| Der Server schickt die ankommenden Daten unverändert zurück. daytime
| 13
| TCP/UDP
| Schickt die Uhrzeit auf dem Serverrechner zurück
| ftp
| 21
| TCP
| Protokoll zum Übertragen beliebiger Dateien
| gopher
| 70
| TCP
| Der Vorläufer des http-Protokolls
| smtp
| 25
| TCP
| Simple Mail Transfer Protocol | (Email senden) http
| 80
| TCP
| HyperText Transfer Protocol Standardprotokoll | zum Übertragen von Webseiten geschrieben sind. pop3
| 110
| TCP
| Post Office Protocol Version 3 | (Email empfangen) |
Nachdem man einen URL eingegeben hat, unternimmt z.Bsp. ein Browser folgende Schritte.
Aufbau einer Verbindung
Von dem eingegebenen URL werden zuerst der Hostname und der Port ausgewertet und damit eine
TCP-Verbindung zum Server aufgebaut.
Senden einer GET Anfrage
Als nächstes sendet der Client eine GET Anfrage, in der er mitteilt, auf welche Datei er (lesend)
zugreifen möchte und welches Protokoll er verwendet, dies kann z.B. folgendermaßen aussehen.
In der GET Anfrage findet man nur noch eine relative Adresse. Die Anfrage wird von einem WebServer
entgegengenommen. Diese Software auf dem Server bildet den relativen Pfad ab auf einen physikalischen.
Apache, der im Internet am weitesten verbreitete Webserver (in der Regel auf Linux laufend) bildet
den relativen Pfad, je nach Konfiguration, etwa ab auf /html/path/to/fileName.html. Der Pfad überhalb
von /html hängt von der Installation des Webservers auf dem Server ab und bleibt dem Client verborgen.
Der REQUEST Header
Im Normalfall ist die GET Anfrage nur der erste Teil eines Headers, in dem der Client dem Server auch
noch mitteilt, wer er ist und welche Antworten er versteht. Das sieht beim Internet Explorer etwa so aus:
Es ist also nichts besonderes, wenn ihnen auf einer website mitgeteilt wird, welchen Browser
und welches Betriebsystem sie benützen und die Antwort auch noch in ihrer Heimatsprache gesendet wird.
Diese Daten sendet ja ein Browser zusammen mit der GET Anfrage. Wichtig ist, daß die gesamte Anfrage mit
zwei vollständigen Zeilenumbrüchen beendet werden muß.
Hier noch eine GET-Anfrage, die von einem Netscape Browser geschickt wurde.
RESPONSE Header und RESPONSE (Die Antwort des Servers)
Die Antwort des Servers besteht aus zwei Teilen, einem Header, in dem er mitteilt, wie er auf
die Anfrage reagiert und einem Datenteil, dem BODY, der meist den Inhalt einer HTML-Datei auf dem
Server enthält. Der BODY der RESPONSE darf nicht verwechselt werden mit dem body-Tag eines HTML-Textes.
Hat man etwa eine Datei angefordert, die der WebServer nicht unter dem übertragenen Pfad findet,
so schaut eine Antwort des Apache Webservers wie folgt aus :
Ein Browser, der diese Daten empfängt, erkennt aus dem ResponseHeader, daß die gewünschte Datei
nicht verfügbar ist (HTTP Fehlercode 404) und daß er eine HTML-Datei mit einer entsprechenden
Fehlermeldung angeboten bekommt. Je nach dem, welchen Browser man verwendet, wird man entweder die
übermittelte HTML-Datei dargestellt bekommen oder eine Meldung, die der Browser auf Grund des
Headers selbst generiert. InternetExplorer verwirft den übertragenen BODY und bringt eine eigene Meldung,
Netscape dagegen bringt genau die im BODY übertragene HTML-Datei. (Nebenbei bemerkt unterdrückt
InternetExplorer die Information, um welchen WebServer es sich auf Serverseite handelt, könnte das
daran liegen, daß die meisten WebServer Apache benützen und nicht den MS-WebServer ??? )
Hat man eine Datei angefordert, die der WebServer findet, so teilt der Webserver dies im AntwortHeader
mit und liefert im BODY die Datei. Antwort des Apache Webservers :
Aus diesen Beispielen erkennt man, daß es offensichtlich bestimmte Schlüsselwörter gibt, die in einem Header stehen können. Welche Schlüsselwörter verwendet werden können oder dürfen, wird von einer Art Normierungsinstanz im Internet festgelegt, die man unter dem Kürzel RFC (Request for Comments) findet. Unter www.rfc-editor.org liest man folgende Erklärung:
Die mittlerweile mehr als 3500 Veröffentlichungen findet man u.a. unter
Internet RFC/STD/FYI/BCP Archives.
Hier gibt es mehrere Indices, nach denen man dieses Archiv durchsuchen kann.
Aus den Beispielen ist der Aufbau eines Headers klar zu erkennen. Bei einer Anfrage enthält die
erste Zeile nach GET den Namen der gewünschten Datei und das Protokoll, das der Client versteht.
Die erste Zeile der Antwort bestätigt das Protokoll und gibt einen Responsecode zurück, der etwas über
Erfolg oder Mißerfolg der Anfrage aussagt. Ab der zweiten
Zeile sind REQUEST und RESPONSE Header gleich aufgebaut. In der Form
keyword: keyvalue
wird Information übermittelt. Welche Schlüsselwörter hier zulässig sind und welche für REQUEST
oder RESPONSE oder beides verwendet werden können findet man unter
Internet RFC/STD/FYI/BCP Archives.
Hier gibt es mehrere Indices, nach denen man dieses Archiv durchsuchen kann.
Einen Auszug aus diesem Papier findet man in den Tabellen am Ende dieses Kapitels
Mögliche Schlüsselworte im Header.
Accept und Content-Type tauchen Werte auf wie
text/plainodertext/htmloderimage/jpeg usw. Diese Werte werden
MIME-Typen (Multipurpose Internet Mail Extension) genannt. Eine kleine Liste dieser Typen
findet sich ebenfalls in den Tabellen am Ende dieses Kapitels
Liste wichtiger MIME-Typen.
Zwei weitere Tabellen sind hier noch zu finden
HTTP RESPONSE-Codes.
Verweise auf einige interessante RFC-Artikel.
Die Klasse URL
Mit der Klasse URL bekommt eine Zeichenkette, die ein Protokoll und die Adresse eines Hosts enthält
einen eigenen Typ. Mit einem URL-Objekt wird aber noch keine Verbindung zum Server aufgebaut. Hier ein
Auszug aus der API.
Konstruktoren | |
URL(String spec) | Creates a URL object from the String representation. |
URL(String protocol, String host, int port, String file) | Creates a URL object from the specified protocol, host, port number, and file. |
URL(String protocol, String host, String file) | Creates a URL from the specified protocol name, host name, and file name. |
Methoden | |
Returntyp | Name der Methode |
Methoden, die Teile des URL zurückliefern | |
String | getAuthority() Gets the authority part of this URL. |
int | getDefaultPort() Gets the default port number of the protocol associated with this URL. |
String | getFile() Gets the file name of this URL. |
String | getHost() Gets the host name of this URL, if applicable. |
String | getPath() Gets the path part of this URL. |
int | getPort() Gets the port number of this URL. |
String | getProtocol() Gets the protocol name of this URL. |
String | getQuery() Gets the query part of this URL. |
String | getRef() Gets the anchor (also known as the "reference") of this URL. |
String | getUserInfo() Gets the userInfo part of this URL. |
Methoden, die eine Verbindung zum Server herstellen | |
URLConnection | openConnection() Returns a URLConnection object that represents a connection to the remote object referred to by the URL. |
InputStream | openStream() Opens a connection to this URL and returns an InputStream for reading from that connection. |
Das Applet demonstriert einige Methoden aus der Klasse URL. Eine eingegebene Adresse wird
nach Betätigung der Return-Taste in ihre Bestandteile zerlegt. Diese werden dann in einer Tabelle
angezeigt. In der linken Spalte stehen die Namen der aufgerufenen Methoden, rechts davon das Ergebnis,
das diese Methoden liefern. Bei einer ungültigen Adresse erscheint in der Statuszeile eine Fehlermeldung.
Versuchen Sie mal den Unterschied zwischen
Die Methode openStream() stützt sich auf die Klasse URLConnection, wie ein Blick in den Quelltext zeigt.
Mehr zu den Methoden getInputStream() und getOutputStream() der Klasse URLConnection im Kapitel
Die Klasse URLConnection .
Hier der Quellcode des obigen Applets
public final InputStream openStream() throws java.io.IOException
{
return openConnection().getInputStream();
}
Man sieht an diesem Applet sehr schön die eingeschränkten Möglichkeiten eines Applets. Wenn man eine
URL eingibt, die nicht mit "http://www.straub.as" beginnt, dann bekommt man eine AccessControlException
in der Statuszeile angezeigt.
import java.io.*;
import java.net.*;
import java.awt.* ;
import javax.swing.*;
import java.awt.event.*;
public class URLOpenStreamApplet extends JApplet
{
private Container conPane ;
private JLabel statusLabel;
private JTextField adressEingabe ;
private JTextArea tear;
private JScrollPane sp;
private URL url ;
public void init()
{
conPane = getContentPane();
initNorth();
initCenter();
initStatus();
}
private void initCenter()
{
tear = new JTextArea();
tear.setLineWrap(true) ;
tear.setWrapStyleWord(true);
tear.setBackground( new Color(240,240,240) ) ;
tear.setEditable(false);
sp = new JScrollPane(tear);
//sp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
//sp.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
conPane.add(sp,BorderLayout.CENTER);
}
private void initNorth()
{
adressEingabe = new JTextField("http://");// Adresse
adressEingabe.setCaretPosition(adressEingabe.getText().length());
adressEingabe.addActionListener( new AdressAction() );
conPane.add(adressEingabe, BorderLayout.NORTH);
}
private void initStatus()
{
statusLabel = new JLabel(" Statuszeile");
statusLabel.setOpaque(true);
statusLabel.setBackground( new Color(220,230,240) );
statusLabel.setBorder( BorderFactory.createLoweredBevelBorder());
conPane.add(statusLabel, BorderLayout.SOUTH);
}
private String readFromURL(URL url)
throws IOException
{
return readInputStream( url.openStream() );
}
private String readInputStream(InputStream is)
throws IOException
{
BufferedInputStream bis = new BufferedInputStream(is);
int avail = bis.available();
byte[] data = new byte[avail];
bis.read(data);
bis.close();
return new String(data);
}
// nested class AdressAction
class AdressAction implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
try
{
tear.setText( readFromURL( new URL(adressEingabe.getText() ) ) ) ;
}
catch(MalformedURLException ex)
{
statusLabel.setText(" Fehler : "+ex);
}
catch(IOException ex)
{
statusLabel.setText(" Fehler : "+ex);
}
catch(java.security.AccessControlException ex)
{
statusLabel.setText(" Fehler : "+ex);
}
} // end actionPerformed()
} // end nested class
} // end class