Advanced   Java   Services
URL's und die Klasse URL
Back Next Up Home

Ein URL und sein Aufbau


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

protocol://hostname:port/path/to/filename?dataString#locationInFile

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


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)


Die GET Anfrage und der REQUEST Header


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.

GET  /path/to/fileName.html  HTTP  1.1

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:

GET /index.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: de
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: 127.0.0.1:7
Connection: Keep-Alive
\r\n
\r\n

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.


GET /index.html HTTP/1.1
Host: 127.0.0.1:70
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
\r\n
\r\n



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 :


HTTP/1.1 404 Not Found
Date: Thu, 25 Dec 2003 09:59:14 GMT
Server: Apache/2.0.47 (Win32) mod_jk2/2.0.2
Content-Length: 304
Connection: close
Content-Type: text/html; charset=iso-8859-1
\r\n
\r\n
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /agapi.html was not found on this server.<p>
<hr />
<address>Apache/2.0.47 (Win32) mod_jk2/2.0.2 Server at www.amd1600.web Port 80</address>
</body></html>

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 :


HTTP/1.1 200 OK
Date: Thu, 25 Dec 2003 10:02:08 GMT
Server: Apache/2.0.47 (Win32) mod_jk2/2.0.2
Content-Length: 2459
Connection: close
Content-Type: text/html;charset=utf-8
\r\n
\r\n
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
...


Aufbau eines Headers


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:

The Requests for Comments (RFC) document series is a set of technical and organizational notes about the Internet (originally the ARPANET), beginning in 1969. Memos in the RFC series discuss many aspects of computer networking, including protocols, procedures, programs, and concepts, as well as meeting notes, opinions, and sometimes humor. For more information on the history of the .

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
ReturntypName 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 URL Applet


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 getAuthority() und getHost() herauszukriegen, oder den Unterschied zwischen getFile() und getPath().


Das URLOpenStreamApplet


Die Methode openStream() stützt sich auf die Klasse URLConnection, wie ein Blick in den Quelltext zeigt.

public final InputStream openStream() throws java.io.IOException
{
   return openConnection().getInputStream();
}

Mehr zu den Methoden getInputStream() und getOutputStream() der Klasse URLConnection im Kapitel Die Klasse URLConnection .

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.

Hier der Quellcode des obigen Applets

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

top Back Next Up Home