Netzwerkprogrammierung in Java Praktikumsunterlagen

Transcrição

Netzwerkprogrammierung in Java Praktikumsunterlagen
Rheinisch-Westfälische Technische Hochschule Aachen
Lehrstuhl für Informatik IV
Prof. Otto Spaniol
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Netzwerkprogrammierung in Java
Praktikumsunterlagen
Sommersemester 2005
Ralf Wienzek
[email protected]
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
1 Hinweise zum Softwarepraktikum
1.1
Ziel und Inhalt des Softwarepraktikums
Im Rahmen dieses Softwarepraktikums soll das in den bisherigen Vorlesungen erworbene Wissen vertieft und
anhand eines überschaubaren Projekts praktisch angewendet werden. Konkret sollen der Entwurf und die Implementierung einer Netzwerkanwendung in der Programmiersprache Java ge übt werden. Neben der reinen
Programmierung wird zusätzlich Wert auf ausreichende Planung und Dokumentation gelegt.
Es ist ausdrücklich keine Veranstaltung zum Erlernen der Programmiersprache Java. Grundlegende Programmierkenntnisse in Java und die Fähigkeit, fehlende Kenntnisse nach Bedarf eigenständig zu erarbeiten, sind
daher Voraussetzungen zur Teilnahme am Praktikum.
1.2
Organisatorisches und aktuelle Informationen
Alle wichtigen Informationen zu diesem Praktikum werden im Web angek ündigt. Hierzu existiert eine Homepage, die Sie über die Seiten des Lehrstuhls für Informatik 4 erreichen können:
http://www-i4.informatik.rwth-aachen.de → Teaching
Auf dieser Seite sind alle benötigten Materialien und einige nützliche Links zu finden. Des Weiteren ist ein
geschützter Bereich für interne Ankündigungen und Materialien eingerichtet. Die Zugangsdaten hierf ür sind:
Benutzername: swpSS05 ; Passwort: p2pMarket
Weitere organisatorische Hinweise:
• Zur Bearbeitung der Aufgaben sind der rote und gelbe Raum des Rechnerpools im Informatikgeb äude
Dienstags und Mittwochs zwischen 14:00 und 17:00 Uhr reserviert. Die Abnahme der Aufgaben erfolgt
zu diesen Zeiten an einem der dortigen Rechner.
• Die Aufgaben sollen in Gruppen von 3 Studenten bearbeitet werden.
• In der Regel stehen 2 Wochen für die Bearbeitung einer Aufgabe zur Verfügung. Diese Zeit kann sich
jede Gruppe frei einteilen und zu Hause oder im Rechnerpool arbeiten. Zu jeder Aufgabe ist ein sp ätester
Abgabetermin angegeben, bei Bedarf kann eine Abgabe jedoch auch schon fr üher erfolgen.
• Bei der Abnahme einer Aufgabe besteht für alle Teilnehmer der Gruppe Anwesenheitspflicht!! Um
zu verhindern, dass mehrere Gruppen gleichzeitig ihre Programme abgeben m öchten und es zu unnötigen
Wartezeiten kommt, muss vorher ein fester Termin vereinbart werden. Hierzu steht in dem gesch ützten
Bereich der Homepage ein entsprechendes Formular zur Verf ügung, in das sich jede Gruppe bis spätestens einen Tag vor der geplanten Abgabe eintragen muss. F ür den Fall, dass mehrere Gruppen zur selben
Zeit abgeben möchten, gilt wer zuerst kommt, malt zuerst“ (in Fachkreisen auch FCFS genannt).
”
• Für das Praktikum ist es notwendig, Zugang zu den Rechnern im Rechnerpool zu besitzen. Wer noch
keinen Account besitzt, kann diesen bei der Rechnerberatung beantragen.
1.3
Arbeitspakete und deren Bearbeitung
Das Praktikum umfasst insgesamt 6 Aufgabenpakete mit Programmieraufgaben. Die Bearbeitung eines Aufgabenpakets besteht grundsätzlich aus den folgenden Schritten:
Ralf Wienzek, [email protected]
1
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
1. Entwurf und Dokumentation des Programms zur Lösung der Aufgabenstellung. Dies kann z.B. anhand
eines Klassendiagramms erfolgen.
2. Unterteilung des Aufgabenpakets in Arbeitspakete und deren Verteilung auf die Gruppenmitglieder. Ein
Arbeitspaket kann beispielsweise die Implementierung einer Klasse umfassen, inklusive Test und Dokumentation. Dabei ist auf eine ausreichend detaillierte Definition des Arbeitspakets zu achten, sodass ein
Gruppenmitglied das Paket möglichst unabhängig von den anderen Paketen bearbeiten kann.
3. Erstellen eines Zeitplans, aus dem hervorgeht, bis wann die Arbeitspakete spätestens abgearbeitet sein
müssen und wann die Integration und das Testen der Gesamtl ösung stattfindet.
4. Abarbeitung der Arbeitspakete
5. Zusammenfügen der einzelnen Arbeitspakete zur Gesamtlösung der Aufgabe
6. Testen und Dokumentieren der Gesamtlösung
Zu jedem Aufgabenpaket übernimmt ein Gruppenmitglied die Rolle des Projektleiters, der f ür die Koordination
der Arbeiten verantwortlich ist. In sein Aufgabengebiet fällt insbesondere die Dokumentation der Schritte 1-3.
Bei der Abnahme der Aufgabe ist der Bericht des Projektleiters“ und eine Übersicht des Gesamtsystems (z.B.
”
als Klassendiagramm) vorzulegen sowie kurz zu erklären. Des Weiteren soll der Projektleiter einen Überblick
über den Fortschritt der Arbeiten behalten, indem regelmäßig Erkundigungen nach dem aktuellen Stand der
Arbeiten eingeholt werden. Dadurch können Probleme frühzeitig erkannt und behoben werden.
Es sei ausdrücklich darauf hingewiesen, dass die beschriebenen Aufgaben des Projektleiters nicht unbedingt
von dem entsprechenden Teammitglied alleine bewältigt werden sollen, sondern durchaus in Diskussion mit
den anderen!!
1.4
Spielregeln oder wie bekomme ich einen Schein?
Einen Praktikumsschein bekommen Teilnehmer, die folgende Bedingungen erf üllen:
• Ausreichende Beteiligung an der Bearbeitung der Aufgabenpakete
• Anwesenheit bei den Abnahmen aller Aufgabenpakete
• Erfolgreiche Abgabe (s.u.) aller Praktikumsaufgaben, durch eigenen Programmcode sowie ausreichender Dokumentation
Die Abnahme eines Aufgabenpakets besteht aus den folgenden Schritten und findet im Rechnerpool statt:
• Vorführen des Programms (alle Gruppenmitglieder)
• Erklären des Programmdesigns anhand des Klassendiagramms (Projektleiter)
• Erklären der einzelnen Arbeitspakete (Projektleiter)
• Erklären des Programmcodes (jeweiliger Bearbeiter)
Nach erfolgreicher Abnahme erfolgt die Abgabe in elektronischer Form:
• Erzeugen einer JAR-Datei, die alle bisher angelegten Packages umfasst (sowohl .java- als auch .classDateien). Der Name der JAR-Datei lautet AiG j.jar“, wobei i die Nummer des Aufgabenpakets und j die
”
Gruppennummer ist.
Ralf Wienzek, [email protected]
2
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
• Erzeugen einer ZIP-Datei namens AiG j.zip“ mit folgendem Inhalt:
”
– die im vorherigen Schritt erzeugte JAR-Datei
– Bericht des Projektleiters
– Klassendiagramm zur Dokumentation des Gesamtsystems
– alle weiteren Dateien zur Dokumentation der Aufgabe
• Email an [email protected] mit angehängter ZIP-Datei und dem Subject
SWP-Abgabe: AiG j
1.5
Dokumentation des Programmcodes
Java unterstützt den Programmierer bei der Dokumentation des Quellcodes durch so genannte doc comments“.
”
Diese Kommentare beginnen mit /** und enden mit */. Innerhalb eines Dokumentationskommentars werden
Tags verwendet, um besondere Informationen zu kennzeichnen.
Das Programm javadoc erstellt aus diesen Kommentaren eine Dokumentation zum Quellcode. Informieren
Sie sich über die Funktionsweise von javadoc und die unterstützten Tags.
Dokumentieren Sie Ihren Quellcode ausführlich mit Hilfe von Dokumentationskommentaren, sodass sich ein
fremder Programmierer in kurzer Zeit in Ihr Programm einarbeiten kann. Insbesondere sind folgende Dinge
ausführlich zu beschreiben:
Klassen Beschreiben Sie den Zweck jeder Klasse ausführlich. Es muss ersichtlich werden, wie Objekte dieser
Klasse verwendet werden sollen. Bestehen Abhängigkeiten oder Querverbindungen zu anderen Klassen,
müssen diese beschrieben sein. Informationen zu Autoren, Version, Datum und Entwicklungsgeschichte
müssen enthalten sein.
Klassenvariable Beschreiben Sie den Zweck einer Klassenvariable, sowie wo und wie sie verwendet wird.
Darf eine Klassenvariable nur bestimmte Werte enthalten, sollten diese beschrieben werden.
Methoden Beschreiben Sie den Zweck jeder Methode. Weiterhin m üssen alle Methodenparameter, ihr Rückgabewert und Situationen, in denen Exceptions geworfen werden, beschrieben werden. Analog zur Beschreibung von Klassen, sollten Abhängigkeiten zu anderen Methoden oder Klassen beschrieben werden.
Informationen zu Autoren, Datum, Version und Entwicklungsgeschichte d ürfen nicht fehlen.
Programmablauf Kommentieren Sie Schlüsselstellen des implementierten Algorithmus.
1.6
Verwendung des Versionsverwaltungssystems Subversion
Subversion ist ein freies Versionsverwaltungssystem, das die parallele Arbeit an Dokumenten innerhalb eines
Teams ermöglicht. Es wird beispielsweise verhindert, dass Änderungen eines Teammitglieds aufgrund der parallelen Bearbeitung des Dokuments durch ein anderes Teammitglied ohne Bestätigung verloren gehen. Zusätzlich speichert Subversion die Historie aller Dokumente und erm öglicht die Wiederherstellung älterer Versionen
des gesamten Projekts oder einzelner Dateien.
Subversion verwaltet Dokumente eines Projekts in einem so genannten Repository. Zur Kommunikation mit
dem Repository verwendet der Entwickler spezielle Clients, wie z.B. svn. F ür die gängigen Betriebssysteme
sind diverse Clients frei verfügbar und werden auf der Homepage zur Verfügung gestellt.
Im Allgemeinen wird zunächst eine Version des Projekts vom Repository angefordert und als lokale Kopie in
das Verzeichnis des Entwicklers abgelegt. Auf dieser Kopie wird anschließend gearbeitet und die durchgef ührten Änderungen werden in das Repository eingefügt. svn bietet eine Vielzahl von Befehlen und Optionen,
Ralf Wienzek, [email protected]
3
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
von denen im Folgenden die wichtigsten kurz erläutert werden. Für detaillierte Erklärungen sei auf das Handbuch verwiesen, das ebenfalls auf der Praktikums-Homepage zum Download bereitsteht. Andere Clients bieten
eine vergleichbare Funktionalität, jedoch kann der konkrete Aufruf der Funktionen variieren. Des Weiteren
gibt es ein Plugin für die Entwicklungsumgebung Eclipse, das eine komfortable Integration von Subversion
ermöglicht.
• svn import [PFAD] <URL>: Legt eine Kopie des angegebenen lokalen Pfades in das Repository. Dieser
Befehl wird normalerweise zur Initialisierung des Repositories verwendet.
• svn checkout <URL>: Kontaktiert das Repository und speichert eine Kopie der aktuellen Version des
Projekts in das aktuelle lokale Verzeichnis. Die anzugebene URL identifiziert eindeutig das Projekt innerhalb des Repositories.
Beispiel: svn checkout svn://fanny.informatik.rwth-aachen.de/swp05/Gruppe1
• svn update: Bringt eine lokal vorhandene Kopie des Projekts auf den neuesten Stand, indem das Repository kontaktiert wird und zwischenzeitlich durchgeführte Änderungen der anderen Entwickler ausgelesen
und in die lokale Kopie eingepflegt werden.
• svn add <filename>: Nimmt eine lokal erzeugte Datei in das Verwaltungssystem auf und wird diese
beim nächsten commit (s.u.) an das Repository übertragen.
• svn delete <filename>: Teilt Subversion mit, dass eine Datei aus dem Projekt entfernt wurde.
• svn status: Gibt eine Liste aller lokalen Dateien und Verzeichnisse aus, die seit dem letzten commit
vom Entwickler verändert wurden. Hiermit kann z.B. überprüft werden, dass wirklich nur die Änderungen durchgeführt wurden, die vorgenommen werden sollten, oder zu Dokumentationszwecken noch
einmal nachvollzogen werden, welche Änderungen durchgeführt wurden.
• svn diff: Gibt die durchgeführten Änderungen im standardisierten Diff-Format aus.
• svn revert <filename>: Macht durchgeführte Änderungen an der angegebenen Datei rückgängig.
• svn resolve <filename>: Dient der Behandlung auftretender Konflikte, d.h. eine Datei die man selbst
geändert hat, wurde gleichzeitig von einem anderen Teammitglied geändert und es muss geklärt werden,
welche Änderungen übernommen werden sollen. Zur genauen Verwendung von resolve sei auf das
oben erwähnte Handbuch verwiesen.
• svn commit -m <Kommentar> bzw. svn commit --file <filename>: Schreibt die lokal durchgef ührten Änderungen in das Repository und legt dabei automatisch eine neue Version des Projekts an. Um die
Historie des Projekts nachvollziehen zu können, muss bei jedem commit ein Kommentar übertragen werden, durch den die durchgeführten Änderungen erklärt werden. Ein kurzer Kommentar kann durch den
Parameter -m angegeben werden. Fällt der Kommentar jedoch länger aus oder wurde parallel zum Bearbeiten der Dokumente gepflegt, sollte er in einer eigens daf ür erstellten Datei abgelegt und svn der
entsprechende Dateiname übergeben werden.
Beispiel: svn commit -m "Meine Änderungen"
Die Zugangsdaten zu den eingerichteten Repositories der einzelnen Gruppen werden per Email versandt.
Ralf Wienzek, [email protected]
4
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
2 Aufgabenstellung
Im Laufe des Praktikums soll ein virtueller Marktplatz zum An- und Verkauf elektronischer Dokumente implementiert werden. Üblicherweise besteht dieser aus einem zentralen Server, auf dem Verkäufer Angebote hinterlassen und Käufer Gebote abgeben können. Diese Architekturen haben jedoch den entscheidenden Nachteil,
dass das gesamte System von der Verfügbarkeit dieses zentralen Servers abhängt. Bei größeren Systemen kann
dieser zudem einen Engpass darstellen und er bietet ein ideales Ziel f ür bösartige Nutzer, die die Funktionalität
des Systems beeinträchtigen möchten.
Es soll daher auf das Konzept eines zentralen Servers verzichtet und stattdessen ein so genanntes Peer-to-PeerNetz (P2P-Netz) aufgebaut werden. Ein P2P-Netz ist ein dynamischer Zusammenschluss gleichberechtigter
Knoten, die ein gemeinsames Ziel verfolgen und dafür geeignet miteinander kommunizieren. Ein teilnehmender
Knoten kann sowohl Dokumente von anderen Knoten beziehen, d.h. als Client agieren, als auch Dokumente
anbieten, d.h. als Server agieren. Er wird daher häufig als Servent bezeichnet. Jeder Servent ist in der Regel
mit einer relativ kleinen Teilmenge der übrigen Netzteilnehmer direkt über eine TCP-Verbindung verbunden.
Um Nachrichten auch an weiter entfernt liegende Servents, zu denen keine direkte Verbindung besteht, senden
zu können, hat jeder Servent zusätzlich die Aufgabe, Nachrichten anderer Servents geeignet weiterzuleiten (so
genanntes Routing). Das in diesem Praktikum zu verwendende Protokoll basiert auf dem bekannten GnutellaProtkoll und wird im Anhang A beschrieben.
Die bisher durch das P2P-Protokoll abgedeckten Funkionalitäten regeln lediglich das Auffinden und Übertragen von im P2P-Netz vorhandenen Dokumenten. Zusätzlich wird ein Bezahlmechanismus zur Abrechnung
benötigt. In diesem Praktikum soll neben dem P2P-Netz eine einfache Bankinfrastruktur bereit gestellt werden. Während der Dokumentenübertragung teilt der Verkäufer dem Käufer seine Bankverbindung mit und der
Käufer überweist den geforderten Betrag nach Abschluss der Transaktion. Eine Bank ist dabei ein außerhalb des
P2P-Netzwerks agierender Server, der Anfragen von Kunden (hier: Servents) und anderen Banken verarbeitet.
Das Protokoll zur Kommunikation mit einer Bank ist in Anhang B beschrieben.
Die Aufgabe jeder Gruppe besteht darin, einen Servent zu entwickeln, der gleichzeitig die Rolle eines Verk äufers
und die eines Käufers übernehmen kann und sich an der Aufrechterhaltung des P2P-Netzwerks beteiligt. Des
Weiteren ist der Servent in der Lage, mehrere Geldkonten des Benutzers bei u.U. unterschiedlichen Bankservern
zu verwalten. Der Benutzer soll die zum Verkauf stehenden lokalen Dokumente unter Angabe eines Mindestpreises und einer Kontoverbindung bei seinem Servent freigeben k önnen. Der Servent antwortet automatisch
auf passende Suchanfragen anderer Servents und überträgt angeforderte Dokumente einschließlich der vom
Benutzer angegebenen Kontoverbindung an die Käufer. Nach einer erfolgreichen Übertragung des Dokuments
werden diesem Konto die Verkaufserlöse gutgeschrieben. Des Weiteren soll der Servent auch als Käufer agieren können, indem er dem Benutzer ermöglicht, Suchanfragen in das P2P-Netz abzusetzen und nach Erhalt von
Suchergebnissen den Kauf eines Dokuments zu initiieren. Hierbei ist vom Benutzer eine der verwalteten Kontoverbindungen auszuwählen, von der bei erfolgreichem Empfang des Dokuments der ausgehandelte Betrag an
den Verkäufer automatisch überwiesen wird.
Im Laufe des Praktikums werden die zu entwickelnden Klassen in drei Java-Packages abgelegt:
• p2pServent fasst alle Klassen zusammen, die unmittelbar mit der Servent-Funktionalität zu tun haben
• p2pBank enthält Klassen zur Implementierung des Bankservers und der Kontenverwaltung innerhalb des
Servents
• p2pUtil enthält Hilfsklassen, die nicht für die Funktionalität des Servents notwendig sind und beispielsweise für Debug-Zwecke verwendet werden können
Die gesamte Aufgabenstellung ist in die folgenden 6 Aufgabenpakete untergliedert, in denen nach und nach
der vollständige Servent implementiert werden soll. Das erste Aufgabenpaket dient der Einarbeitung in die
Ralf Wienzek, [email protected]
5
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Netzwerkprogrammierung. Es wird ein nützliches Werkzeug entwickelt, das später zur Analyse des Netzwerkverkehrs verwendet werden kann und hilfreich bei der Fehlersuche ist. Im zweiten Aufgabenpaket wird die
Server- und Clientseite des Bankprotokolls implementiert. Die Aufgabenpakete 3-6 implementieren die einzelnen Servent-Funktionen. Das letzte Paket dient dem Testen der verschiedenen Implementierungen auf Kompatibilität untereinaner.
Ralf Wienzek, [email protected]
6
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
3 Aufgabenpakete
Aufgabenpaket 1: TCP-Proxy
Abgabe: 26./27. April
Das Ziel dieses Aufgabenpakets besteht darin, sich in die Netzwerkprogrammierung in Java einzuarbeiten.
Um die Fehlersuche bei den später zu implementierenden Kommunikationsprotokollen zu erleichtern, soll ein
einfacher Proxy programmiert werden, der zwischen einem Client und einem Server platziert wird und die
weitergeleiteten Nutzdaten auf dem Bildschirm ausgibt. Die Funktionalität ist in der folgenden Abbildung
skizziert.
Client
Proxy
Server
Port X
abhören
Port Y
abhören
Verbindung
sa
ufbau
Daten für S
Verbindung
saufbau
erver
Daten
ausgeben
Daten für S
erver
Daten
verarbeiten
t
en
Daten für Cli
ent
Daten für Cli
Daten
ausgeben
Normalerweise würde der Client eine direkte Verbindung zum Server aufbauen, über die Daten in beide Richtungen ausgetauscht werden können. In diesem Fall baut der Client jedoch zunächst eine Verbindung zum
Proxy auf, der sich seinerseits mit dem Server verbindet. Die Aufgabe des Proxies besteht darin, alle Daten,
die von einem der Kommunikationspartner ankommen, unverändert an den anderen weiterzuleiten. Aus Clientund Serversicht besteht also kein Unterschied, ob ein Proxy aktiv ist oder nicht. Zusätzlich zur Weiterleitung
der Daten, gibt der Proxy sie auf dem Bildschirm im folgenden Format aus:
• Die Daten werden in Blöcke zu je 8 Bytes unterteilt (der letzte Block ist evtl. kleiner).
• Jeder Block wird auf einer Zeile ausgegeben.
• Jede Zeile beginnt mit C: oder S:, je nachdem ob die Daten vom Client oder vom Server gesendet
wurden. Darauf folgen die 8 Bytes des Blocks als zweistellige Hexadezimalzahlen (jeweils durch ein
Leerzeichen getrennt und u.U. mit führender Null). Es folgen drei Leerzeichen und die 8 Bytes des
Blocks als dreistellige Dezimalzahlen (jeweils durch Leerzeichen getrennt, rechts ausgerichtet und ohne
führende Nullen). Nach weiteren drei Leerzeichen werden die 8 Bytes als Buchstaben im ISO-8859-1
Zeichensatz dargestellt (ohne Leerzeichen getrennt und nicht darstellbare Zeichen als “.” kodiert).
Beispiel: Darstellung von Hallo Welt!\n
Ralf Wienzek, [email protected]
7
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
S: 48 61 6C 6C 6F 20 57 65
S: 6C 74 21 0A
72 97 108 108 111
108 116 33 10
32
87 101
Hallo We
lt!.
Um den Tcp-Proxy testen zu können, soll zusätzlich ein kleiner Server implementiert werden. Dieser hat die
Aufgabe, die Buchstaben einer eingehenden Textzeile in umgekehrter Reihenfolge an den Client zur ückzuschicken. Er öffnet einen lokalen Port und wartet auf Verbindungsanfragen. Nachdem eine Verbindung aufgebaut
wurde, erwartet er im ISO-8859-1 Zeichensatz kodierte Strings, die zeilenweise bearbeitet werden. Eine Zeile
endet mit einem Zeilenumbruch (Zeichen 0x0A), der nicht zu der zu verarbeitenden Zeile gez ählt wird. Der Server sendet anschließend die Zeichen in umgekehrter Reihenfolge zur ück und beendet die Zeile seinerseits mit
einem Zeilenumbruch. Dies wird solange fortgeführt, bis der Client die TCP-Verbindung beendet, woraufhin
sich der Server ebenfalls beendet.
Beispiel: Verarbeitung von Hallo Welt!\n
Eingabe: 48 61 6C 6C 6F 20 57 65 6C 74 21 0A
Ausgabe: 21 74 6C 65 57 20 6F 6C 6C 61 48 0A
Aufgabe:
• Entwerfen und implementieren Sie die Klasse TcpProxy im Package p2pUtil. Die Anwendung erwartet
drei Parameter: eine lokale Portnummer, einen Rechnernamen und einen Serverport. Die Portnummern
sind jeweils positive Integer zwischen 1 und 65535 und der Rechnername kann entweder der Name
eines Rechners oder dessen IP-Adresse sein. Die Anwendung öffnet den angegebenen lokalen TCPPort und wartet auf Verbindungen. Sollte dies nicht möglich sein, bricht sie mit einer entsprechenden
Fehlermeldung ab. Sobald eine Verbindung von einer anderen Anwendung aufgebaut wurde, baut der
TcpProxy seinerseits eine Verbindung zum angegebenen Server auf und verarbeitet die Daten wie oben
beschrieben. Sollte eine Verbindung zum Server nicht m öglich sein, bricht die Anwendung ebenfalls mit
entsprechender Fehlermeldung ab.
• Entwerfen und implementieren Sie die Klasse ReverseEcho im Package p2pUtil. Die Anwendung erwartet als einzigen Parameter eine lokale Portnummer. Sollte der angegebene Port nicht abgeh ört werden
können, bricht sie mit entsprechender Fehlermeldung ab.
• Testen und dokumentieren Sie Ihre Implementierung ausreichend.
Demonstration bei der Abnahme:
1. Auf Rechner A: java p2pUtil.ReverseEcho 12345
2. Auf Rechner B: java p2pUtil.TcpProxy 23456 A 12345
3. Auf Rechner C: telnet B 23456 und Eingabe einiger Zeilen Text
Interessante Klassen:
• java.net.*, insbesondere Socket und ServerSocket
• java.io.*, insbesondere InputStream und OutputStream
• Thread, byte[], String (z.B. String(byte[],charsetName) und String.getBytes(..))
• Alternativ: java.nio.channels.ServerSocketChannel, java.nio.channels.Selector,
java.nio.ByteBuffer
Ralf Wienzek, [email protected]
8
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 2: Bank
Abgabe: 10./11. Mai
Im Zuge dieses Aufgabenpakets sollen der Bankserver und eine entsprechende Klasse zur Kontoverwaltung
innerhalb des Servents implementiert werden. Anders als der textbasierte Tcp-Proxy interagiert der Bankserver
über eine graphische Benutzeroberfläche (GUI) mit dem Benutzer. Die Gestaltung der Oberfläche bleibt Ihrer
Kreativität überlassen, sie muss jedoch zweckmäßig sein.
Nach dem Programmstart öffnet sich zunächst die Oberfläche zur Administration der Bank, ohne dass der
eigentliche Server gestartet wird. Der Administrator (Bankdirektor) hat folgende M öglichkeiten:
• Einstellen der TCP-Portnummer, auf welcher der Server laufen soll.
• Start des Servers, falls dieser nicht läuft.
• Anhalten des Servers, falls dieser läuft.
• Auflisten aller Konten, inklusive der aktuellen Kontostände.
• Editieren der Kontostände.
• Löschen von Konten.
Nachdem der Server gestartet wurde, kommuniziert er gemäß des Protokolls aus Anhang B mit Kunden und
anderen Bankservern. Es sollen mehrere Verbindungen gleichzeitig verarbeitet werden k önnen, d.h. nachdem
eine Verbindung angenommen wurde, können weitere entgegengenommen werden, ohne dass bestehende geschlossen werden müssen.
Als Gegenstück zum Server soll eine Klasse realisiert werden, welche das Bankprotokoll des Kunden kapselt
und den Zugriff auf ein Konto über definierte Methodenaufrufe ermöglicht. Im später zu implementierenden
Servent wird für jedes Konto, das der Benutzer eröffnet, eine Instanz dieser Klasse angelegt und vom Servent
verwaltet.
Um die Implementierung des Bankprotokolls unabhängig vom P2P-Protokoll zu halten, soll vom Servent aus
nur über die im Folgenden definierten Schnittstellen auf das Konto eines Benutzers zugegriffen werden. S ämtliche Klassen und Interfaces gehören zum p2pBank-Package.
public abstract class BankAccount {
public static BankAccount open ( String host , int port , String password )
throws OpenBankAccountException
{
...
}
public static BankAccount use ( String host , int port , long accNo , String password )
throws UseBankAccountException
{
...
}
public abstract java . net . InetAddress getIP ();
public abstract int getPort ();
public abstract long getAccountNumber ();
public abstract boolean transfer (
java . net . InetAddress IP , int port , long accNo ,
Ralf Wienzek, [email protected]
9
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
long amount ,
String text );
public abstract AccountStatement getStatement ();
public abstract void closeAccount ();
public abstract String toString ();
}
public interface AccountStatement {
public long getBalance ();
public Transaction [] getTransactions ();
}
public interface Transaction {
public java . net . InetAddress getIP ();
public int getPort ();
public long getAccNo ();
public long getAmount ();
public String getText ();
}
Die statischen Methoden BankAccount.open(..) und BankAccount.use(..) erm öglichen es einem Client,
Objekte zur Verwaltung von Bankkonten anzulegen. Anzugeben sind jeweils die Parameter, die zur Erzeugung
der entsprechenden Nachrichten des Bank-Protokolls aus Anhang B notwendig sind. In beiden F ällen werden
diese Nachrichten abgeschickt und es wird auf Antwort des Bankservers gewartet. Bei Erfolg geben beide
Methoden ein Objekt zurück, welches von BankAccount abgeleitet ist und das Konto repräsentiert. Bei einem
Misserfolg werden entsprechende Exceptions geworfen, die z.B. die Fehlermeldung aus dem Bank-Protokoll
enthalten.
Über die Selektoren getIP(), getPort() und getAccountNumber() k önnen Informationen über die Bankverbindung abgefragt werden. Die Methode transfer(..) st ößt eine Überweisung auf das zu übergebende
Konto an (siehe entsprechende Nachricht des Bank-Protokolls). getStatement() fordert einen Kontoauszug
an und gibt ein Objekt zurück, das die entsprechenden Daten aus der Antwort des Bankservers enthält. Mittels
closeAccount() kann das Konto geschlossen werden. toString() liefert einen String, der das Konto f ür
einen Menschen lesbar beschreibt. Dieser kann im Servent zum Beispiel f ür Auflistungen aller Konten eines
Benutzers verwendet werden.
Aufgabe:
• Implementieren Sie im Package p2pBank die Klasse BankServer zur Realisierung der Bank. Die Anwendung erwartet keine weiteren Kommandozeilenparameter.
• Implementieren Sie im Package p2pBank die oben beschriebene Klasse BankAccount, sodass durch
try {
BankAccount ba1 = BankAccount . open ( " < Adresse >" , 12345 , " geheim " );
BankAccount ba2 = BankAccount . use ( " < Adresse >" , 12345 , 7 , " geheim " );
} catch ( Exception e ) {
System . err . println ( " Fehler bei Kontoeröffnung : " + e. getMessage () );
}
ein Konto eröffnet bzw. weiter benutzt werden kann.
• Implementieren Sie im Package p2pBank die Klasse Testclient1. Sie besitzt eine main()-Methode, die
3 Parameter (host, port, password) auf der Kommandozeile erwartet und ein Konto beim angegebenen
Bankserver anlegt. Bei Erfolg werden die zugewiesene Kontonummer und der initiale Kontostand auf
dem Bildschirm ausgegeben.
Ralf Wienzek, [email protected]
10
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
• Implementieren Sie im Package p2pBank die Klasse Testclient2. Sie besitzt eine main()-Methode, die
7 Parameter (host1, port1, accNo1, password1, host2, port2, password2, password3) erwartet. Sie f ührt
die folgenden Operationen aus und informiert den Benutzer durch aussagekräftige Bildschirmausgaben
über deren Ergebnisse:
BankAccount ba1 = BankAccount . use ( host1 , port1 , accNo1 , password1 );
BankAccount ba2 = BankAccount . open ( host2 , port2 , password2 );
BankAccount ba3 = BankAccount . open ( host2 , port2 , password3 );
long accNo1 = ba1 . getAccountNumber ();
long accNo3 = ba3 . getAccountNumber ();
ba1 . getStatement ();
ba2 . getStatement ();
ba3 . getStatement ();
ba2 . transfer ( host2 , port2 , accNo3 , 1 , " Test1 " );
ba2 . transfer ( host1 , port1 , accNo1 , 1 , " Test2 " );
ba1 . getStatement ();
ba2 . getStatement ();
ba3 . getStatement ();
ba1 . closeAccount ();
ba3 . closeAccount ();
ba2 . transfer ( host2 , port2 , accNo3 , 1 , " Test3 " );
ba2 . transfer ( host1 , port1 , accNo1 , 1 , " Test4 " );
• Geben Sie an, welche Ausgaben die TcpProxies in dem im Folgenden beschriebenen Demo-Szenario
machen sollten. Verwenden Sie hierfür eine geeignete Kurznotation.
Demonstration bei der Abnahme:
1. Rechner A: Starten eines Bankservers auf Port 5001, starten eines Tcp-Proxies:
java p2pUtil.TcpProxy 5000 A 5001
2. Rechner B: Starten eines Bankservers auf Port 5001, starten eines Tcp-Proxies:
java p2pUtil.TcpProxy 5000 B 5001
3. Starten des 1. Testclients:
java p2pBank.TestClient1 A 5000 geheim
4. Starten des 2. Testclients:
java p2pBank.TestClient2 A 5000 <accNo> geheim B 5000 secret secure
wobei <accNo> die erhaltene Kontonummer beim Lauf von TestClient1 ist.
Ralf Wienzek, [email protected]
11
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 3: Servent - Kontoverwaltung, P2P-Verbindungen
Abgabe: 31. Mai / 1. Juni
In diesem Aufgabenpaket soll mit der Implementierung des Servents begonnen werden. Die im Package p2pServent
zu implementierende Klasse MarketServent stellt den Startpunkt der Anwendung dar. Nach dem Start befindet sich der Servent zunächst im Offline-Modus, d.h. Verbindungen zu und von anderen Servents k önnen weder
aufgebaut noch angenommen werden (s.u.).
Der Benutzer interagiert über eine graphische Benutzeroberfläche mit dem Servent und hat folgende Möglichkeiten:
• Wechseln zwischen Offline- und Online-Modus. Wenn vom Offline- in den Online-Modus gewechselt
wird, muss der Benutzer zunächst zwei lokale TCP-Portnummern angeben oder über ein Konfigurationsmenu bereits angegeben haben. Auf dem ersten Port erwartet der Servent eingehende P2P-Verbindungen,
auf dem zweiten sollen Download-Anfragen vom später zu implementierenden HTTP-Server entgegengenommen werden. Beide Server werden gestartet und der Servent nimmt aktiv am P2P-Netz teil, indem
Nachrichten ausgewertet und weitergeleitet werden.
Ein Wechsel vom Online- in den Offline-Modus bewirkt, dass sämtliche offene P2P-Verbindungen geschlossen werden, alle laufenden Down- und Uploads abgebrochen werden und sowohl der P2P- als auch
der HTTP-Server beendet wird.
• Der Benutzer erhält eine Übersicht über alle bestehenden P2P-Verbindungen. Er kann eine bestehende
Verbindung schließen und neue Verbindungen aufbauen. F ür Letzteres muss er die Adresse (Host und
Port) eines anderen Servents eingeben. Dabei ist darauf zu achten, dass keine zwei Verbindungen zum
selben Host aufgebaut werden darf. Diese Funktionalität ist nur im Online-Modus möglich.
• Der Benutzer kann Konten neu eröffnen, bestehende Konten weiterverwenden und Konten schließen.
Er kann sich eine Übersicht über alle von ihm eröffneten Konten anzeigen lassen und Kontoauszüge
anfordern. Dies ist sowohl im Online- als auch im Offline-Modus m öglich.
Hinweis: Die noch folgenden Aufgabenpakete erweitern die hier beschriebene Funktionalit ät des Servents.
Bevor Sie mit dem Entwurf des Servents bzw. dessen graphischer Benutzeroberfläche beginnen, sollten Sie
sich die übrigen Aufgabenpakete auch durchlesen, um diese Funktionalitäten beim Entwurf berücksichtigen zu
können.
Aufgabe:
Entwerfen und implementieren Sie im p2pServent-Package die oben beschriebene Anwendung. Die P2PFunktionalität soll sich zunächst auf den Aufbau von P2P-Verbindungen beschränken. Der Servent muss also abgesehen vom Handshake zum Verbindungsaufbau (siehe Anhang A) noch nicht in der Lage sein, P2PNachrichten zu verarbeiten. Ebenso muss der HTTP-Server noch nicht implementiert werden.
Demonstration bei der Abnahme:
1. Starten von 3 MarketServents auf verschiedenen Rechnern. Starten eines Bankservers.
2. Servent 1: Anlegen von 2 Bankkonten.
Servent 2: Weiterverwenden eines Kontos, das Servent 1 angelegt hat.
Starten von p2pBank.TestClient2 (siehe Aufgabenpaket 2) mit diesem Konto als Konto1.
Servent 2: Auflösen des verwendeten Kontos.
3. Starten von p2pUtil.TcpProxy, wobei Servent 2 als Ziel (Server) angegeben wird.
Ralf Wienzek, [email protected]
12
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
4. Alle Servents in den Online-Modus schalten
Servent 1: Aufbau von P2P-Verbindung zu Servent 2 über den Proxy
Servent 3: Aufbau von P2P-Verbindung zu Servent 1
Servent 1: Offline-Modus aktivieren
Ralf Wienzek, [email protected]
13
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 4: Servent - Freigaben, Ping/Pong
Abgabe: 14./15. Juni
Der im Aufgabenpaket 3 entwickelte Servent soll in diesem Aufgabenpaket um Funktionalit äten zur Freigabe
von Dateien und zum Senden und Verarbeiten von Ping- und Pong-Paketen erweitert werden.
Der Benutzer soll lokale Dateien zum Kauf anbieten können. Hierzu wird er aufgefordert, einen Mindestpreis
und eine seiner bestehenden Kontoverbindungen anzugeben. Auf das angegebene Konto werden sp ätere Verkaufserlöse überwiesen. Des Weiteren kann er Freigaben wieder zur ücknehmen oder den Mindestpreis bzw.
die Kontoverbindung zu einer bestehenden Freigabe editieren. Dies ist sowohl im Online- als auch im OfflineModus möglich. (Hinweis: Für den späteren Download eines Dokuments wird für dessen Identifizierung ein
Index verwendet (siehe Anhang A). Sie sollten dies bereits an dieser Stelle ber ücksichtigen.)
Befindet sich der Servent im Online-Modus, sollen Ping- und Pong-Nachrichten entsprechend den Regeln aus
Anhang A verarbeitet und weitergeleitet werden. Informationen aus allen Pong-Paketen (also nicht nur aus
denjenigen, welche als Antwort auf eigens versendete Pings eingehen) werden kontinuierlich gesammelt und
können vom Benutzer eingesehen werden. Ein Servent wird durch seine IP-Adresse identifiziert und soll in
dieser Liste nicht doppelt vorkommen. Zusätzlich soll zu jedem Servent die Anzahl und Größe seiner Freigaben
angezeigt und bei jedem eingehenden Pong-Paket aktualisiert werden. Der Benutzer hat die M öglichkeit, durch
Auswahl eines Servents eine P2P-Verbindung aufzubauen, falls eine solche Verbindungen nicht bereits besteht.
Im Online-Modus hat der Benutzer des Weiteren die Möglichkeit, eigene Ping-Pakete in das P2P-Netz zu versenden. Der zu verwendende TTL-Wert soll frei konfigurierbar sein. Das Ping-Paket wird über alle bestehenden
Verbindungen versendet.
Aufgabe:
• Erweitern Sie Ihren Servent um die oben beschriebenen Funktionalitäten
• Geben Sie an, welche Ausgaben die TcpProxies in dem im Folgenden beschriebenen Demo-Szenario
machen sollten. Verwenden Sie hierfür eine geeignete Kurznotation.
Demonstration bei der Abnahme:
1. 4 Servents auf unterschiedlichen Rechnern starten, auf den Servents 2-4 Dateien freigeben, alle Servents
in den Online-Modus schalten.
2. Folgende Verbindungen aufbauen, jeweils mit einem TcpProxy aus Aufgabenpaket 1 dazwischen:
1 → 2, 2 → 3, 2 → 4
3. Servent 1 versendet Ping mit TTL von 0
4. Freigaben von Servent 2 ändern
5. Servent 1 versendet Ping mit TTL von 1
6. Servent 1 baut Verbindung zu Servent 3 auf (mit TcpProxy dazwischen)
7. Servent 4 sendet Ping mit TTL von 7
8. Servent 2 wechselt in den Offline-Modus
Ralf Wienzek, [email protected]
14
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 5: Servent - Query/QueryHit
Abgabe: 21./22. Juni
Im Zuge dieses Aufgabenpakets soll der Servent um Funktionalitäten zum Auffinden von passenden Dokumenten innerhalb des P2P-Netzwerk erweitert werden. Die grafische Benutzeroberfläche ist so zu erweitern, dass
der Benutzer einen Suchstring und einen Höchstpreis eingeben kann. Diese Werte werden als Nutzdaten von
Query-Nachrichten im P2P-Netzwerk verteilt. Suchergebnisse sollen geeignet aufgelistet werden, sodass der
spätere Download eines Dokuments vom Benutzer komfortabel angestoßen werden kann (s. Aufgabenpaket 6).
Befindet sich der Servent im Online-Modus, sollen eingehende Query-Nachrichten korrekt verarbeitet und weitergeleitet werden (s. Anhang A). Für jede ankommende Query-Nachricht, die nicht bereits verarbeitet wurde,
wird das in ihr enthaltene Suchkriterium als regulärer Ausdruck interpretiert und mit dem Dateinamen aller
derzeit freigegebener Dateien verglichen. Zusätzlich wird geprüft, ob der vom Benutzer bei der Freigabe geforderte Mindestpreis nicht größer als der durch die Suchanfrage spezifizierte Höchstpreis ist. Gibt es mindestens
eine passende Freigabe, wird vom Servent eine QueryHit-Nachricht mit je einem ResultSet f ür jede passende
Freigabe erzeugt.
Eingehende QueryHits werden nur ausgewertet (und anschließend verworfen), wenn Sie Antworten auf selbst
abgeschickte Queries sind. Andernfalls werden Sie den Routing-Regeln entsprechend weitergeleitet ohne ihren
Inhalt zu verarbeiten.
Aufgabe:
• Erweitern Sie Ihren Servent um die oben beschriebenen Funktionalitäten
• Geben Sie an, welche Ausgaben die TcpProxies in dem im Folgenden beschriebenen Demo-Szenario
machen sollten. Verwenden Sie hierfür eine geeignete Kurznotation.
Demonstration bei der Abnahme:
1. 4 Servents auf unterschiedlichen Rechnern starten, auf den Servents 2-4 Dateien freigeben, alle Servents
in den Online-Modus schalten.
2. Folgende Verbindungen aufbauen, jeweils mit einem TcpProxy aus Aufgabenpaket 1 dazwischen:
1 → 2, 2 → 3, 2 → 4
3. Servent 1 stellt Suchanfrage, die nur Servent 2 erfolgreich beantworten kann
4. Servent 1 stellt Suchanfrage, die nur Servent 3 erfolgreich beantworten kann
5. Servent 1 stellt Suchanfrage, die Servents 2-4 erfolgreich beantworten k önnen
Interessante Klassen:
• String.matches(..)
• Package java.util.regex
Ralf Wienzek, [email protected]
15
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 6: Servent - Up-/Download
Abgabe: 12./13. Juli
Mit diesem Aufgabenpaket sollen die noch fehlenden Funktionalitäten des Servents implementiert werden. Die
grafische Benutzeroberfläche ist so zu erweitern, dass nach Auswahl eines Suchergebnisses und Angabe einer
Kontoverbindung das durch das Suchergebnis identifizierte Dokument heruntergeladen und lokal gespeichert
werden kann. Nach erfolgreichem Download wird der vom Verkäufer geforderte Betrag vom angegebenen
Konto automatisch auf das Konto des Verkäufers überwiesen.
Zusätzlich soll sich der Benutzer den Fortschritt aller aktiven Up- und Downloads ansehen k önnen. In beiden Fällen sollen der Dateiname, der Preis, der Rechner, zu/von dem das Dokument übertragen wird, und der
regelmäßig zu aktualisierende Fortschritt angezeigt werden. Laufende Up-/Downloads sollen vom Benutzer abgebrochen werden können. In diesem Fall wird die zugehörige TCP-Verbindung geschlossen und eine Bezahlung muss nicht erfolgen. Des Weiteren können Informationen über alle erfolgreich beendeten Transaktionen
eingesehen werden. Zu jeder Transaktion werden mindestens die folgenden Informationen bereit gestellt:
• Handelte es sich um einen Kauf oder einen Verkauf
• Adresse des Geschäftspartners
• Eigene Kontoverbindung, bei einem Kauf zusätzlich diejenige des Partners
• Verwendete Rechnungsnummer
Neben diesen für den Benutzer unmittelbar sichtbaren Erweiterungen, ist ein HTTP-Server zu implementieren,
der die drei in Abschnitt A.3 beschriebenen Nachrichten verarbeiten kann. Dieser Server ist nur im OnlineModus auf dem vom Benutzer konfigurierten Port aktiv. Sollte der Benutzer in den Offline-Modus wechseln,
werden alle aktiven Übertragungen abgebrochen und der HTTP-Server stellt die Bearbeitung von Anfragen ein.
Demonstration bei der Abnahme:
1. Rechner A: Starten eines Servents (S1) mit HTTP-Server-Port 8000; Dateien freigeben, darunter mindestens eine große (s. Schritte 3-6) und eine kleine (s. Schritte 7-8)
2. Rechner B: Starten eines Servents (S2); P2P-Verbindung aufbauen; nach den freigegebenen Dateien suchen
3. S2: Download einer (genügend großen) Datei anstoßen und diesen abbrechen
4. S2: Download einer (genügend großen) Datei anstoßen, S1 bricht entsprechenden Upload ab
5. S2: Download einer (genügend großen) Datei anstoßen, S1 wechselt während der Übertragung in den
Offline-Modus
6. S1: HTTP-Server auf Port 8001 konfigurieren und in den Online Modus wechseln
7. Rechner A: TCP-Proxy starten
java p2pUtil.TcpProxy 8000 localhost 8001
8. S2 initiiert Download einer (kleinen!) Datei durch Auswahl eines Suchergebnisses aus Schritt 2
Interessante Klassen:
• java.io.FileInputStream, java.io.FileOutputStream
Ralf Wienzek, [email protected]
16
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
Aufgabenpaket 7: Crosstesten
Abgabe: 19./20. Juli
Ziel dieses Aufgabenpakets ist es, die Kompatibilität der unterschiedlichen Implementierungen zu testen. Der
genaue Ablauf und Testaufbau wird noch bekannt gegeben.
Ralf Wienzek, [email protected]
17
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
A P2P-Protokoll
Das im Folgenden beschriebene Protokoll für das P2P-Netzwerk basiert auf dem Protokoll, das im bekannten
Gnutella-Netzwerk verwendet wird. Es definiert verschiedene Nachrichtentypen, f ür die Suche nach Dokumenten innerhalb des P2P-Netzwerks.
Jeder Servent ist mit einer Anzahl anderer Servents über eine TCP-Verbindung direkt verbunden. Während des
Verbindungsaufbaus zweier Servents findet zunächst ein so genannter Handshake statt. Der Servent, welcher
die TCP-Verbindung initiiert hat, sendet den String
GNUTELLA CONNECT/0.1\n
an seinen Partner. Dieser antwortet mit
GNUTELLA OK\n
und die Verbindung gilt als aufgebaut. Beide Strings werden im ISO-8859-1 Zeichensatz kodiert, wobei der
Zeilenumbruch \n durch 0x0A dargestellt wird. Anschließend k önnen über diese Verbindung P2P-Nachrichten
ausgetauscht werden. Im hier verwendeten Protokoll haben Servents zum einen die M öglichkeit, die Adressen
bisher unbekannter Servents zu ermitteln (Ping-/Pong-Nachrichten), und zum anderen eine netzweite Suche
nach bestimmten Dokumenten zu initiieren (Query-/QueryHit-Nachrichten). Das Herunterladen von Dokumenten geschieht außerhalb des P2P-Netzwerks. Die Suchergebnisse, die ein Servent auf seine Anfrage erh ält,
enthalten vielmehr die Adresse eines HTTP-Servers und weitere Informationen, mit denen die Datei durch den
Aufbau einer separaten TCP-Verbindung angefordert werden kann.
Im Folgenden werden zunächst die P2P-Nachrichten spezifiziert, die über eine aufgebaute Verbindung zwischen
zwei Servents übertragen werden können. Anschließend wird das Routing-Verhalten der Servents definiert und
abschließend beschrieben, wie das Herunterladen von Dokumenten abläuft.
A.1
P2P-Nachrichten
Sämtliche Nachrichten bestehen aus zwei Teilen: einem Header gefolgt von einem Nutzdatenbereich. Der Header ist für jeden Nachrichtentyp gleich aufgebaut und enthält Kontrollinformationen, die für die Verarbeitung
innerhalb der Netzwerkknoten benötigt werden. Der Aufbau und Inhalt des Nutzdatenbereichs hängt vom jeweiligen Nachrichtentyp ab.
A.1.1
Header
Der Header hat eine Länge von 23 Bytes und besteht aus den folgenden Feldern:
Größe in Bytes:
Feld:
16
MessageID
1
PayloadID
1
TTL
1
Hops
4
Payload Length
MessageID Eine 16 Byte große Zahl, die zusammen mit der PayloadID eine Nachricht im gesamten P2PNetzwerk eindeutig identifiziert. Um die Eindeutigkeit zu gewährleisten, bestehen die ersten vier Bytes
aus der IP-Adresse des Senders und die folgenden 2 Bytes aus der Portnummer, auf dem der Servent auf
Verbindungen wartet. Die restlichen 10 Bytes werden als Seriennummer verwendet, die f ür jede neue
Nachricht um 1 erhöht wird.
PayloadID Zeigt an, um welchen Nachrichtentyp es sich handelt. G ültige Werte sind:
• 0x00: Ping
• 0x01: Pong
Ralf Wienzek, [email protected]
18
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
• 0x80: Query
• 0x81: QueryHit
TTL (Time To Live) Zeigt an, wie oft die Nachricht noch weitergeleitet werden darf, bevor sie verworfen
wird. Jeder Servent muss diesen Wert um 1 verringern, bevor er die Nachricht weiterleitet. Enth ält das
Feld den Wert 0, wird die Nachricht zwar noch verarbeitet, jedoch nicht mehr weitergeleitet. Hierdurch
wird verhindert, dass Nachrichten beliebig lange im Netzwerk unterwegs sind. Der Anfangswert h ängt
von der Nachricht ab (s.u.).
Hops Zeigt an, von wie vielen Servents die Nachricht bisher weitergeleitet wurde. Der Sender setzt dieses Feld
auf 0 und jeder Knoten erhöht den Wert um 1, bevor er die Nachricht weiterleitet. Für jede Nachricht
bleibt die Summe aus TTL- und Hops-Feld stets konstant.
Payload Length Enthält die Länge der unmittelbar folgenden Nutzdaten in Bytes.
A.1.2
Ping / Pong
Ping-Anfragen dienen dazu, weitere Servents im P2P-Netzwerk ausfindig zu machen. Jeder Servent, der eine
Ping-Nachricht erhält, antwortet mit einem Pong. Eine Ping-Nachricht hat keine Nutzdaten, besteht also nur
aus dem Header.
Beispiel einer Ping-Nachricht:
137
226
12
131
19
MessageID
136 0 0 0
0
0
0
0
0
0
1
PlID
0
TTL
7
Hops
0
0
Payload Len
0 0 0
Mittels einer Pong-Nachricht teilt der Empfänger einer Ping-Nachricht dem Sender mit, über welche Adresse er
zu erreichen ist (IP-Adresse, Portnummer) und wie viele Dokumente er im Angebot hat. Als MessageID wird
diejenige der zugehörigen Ping-Nachricht übernommen. Das TTL-Feld wird mit dem Hops-Feld der PingNachricht belegt und das Hops-Feld auf 0 gesetzt. Der Nutzdatenbereich der Nachricht ist 14 Bytes groß und
besteht aus den folgenden Feldern:
2
Port
4
IP-Adresse
4
#Shares
4
KByte shared
Port Enthält die Nummer des TCP-Ports, auf welchem der Servent P2P-Verbindungen entgegennimmt.
IP-Adresse IP-Adresse des Servents.
#Shares Anzahl der Dokumente, die vom Benutzer freigegeben wurden.
KByte shared Gesamtgröße der Freigaben in KByte.
Beispiel einer Pong-Nachricht (MessageID verkürzt dargestellt):
MID
...
PlID
1
TTL
4
Header
Hops
0
Payload Len
0 0 0 14
Port
19 136
Pong-Payload
IP-Adresse
#Shares
10 11 12 13 0 0 0 10
0
KByte shared
1 134 160
Der Servent läuft auf dem Rechner mit der IP-Adresse 10.11.12.13, nimmt auf TCP-Port 5000 P2P-Verbindungen
entgegen und hat 10 Dateien mit einer Gesamtgröße von 100 MB freigegeben.
Ralf Wienzek, [email protected]
19
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
A.1.3
Query / QueryHit
Query-Anfragen dienen dazu, nach bestimmten Dokumenten im Netzwerk zu suchen. Der Sender gibt hierzu
ein Suchkriterium und einen maximalen Preis an. Alle Servents, die passende Dokumente freigegeben haben,
antworten mit einer QueryHit-Nachricht.
Die Nutzdaten einer Query-Nachricht haben den folgenden Aufbau:
2
Price
1
Criteria length
var.
Search criteria
Price Enthält den maximalen Betrag, den der Sender bereit ist, für das gesuchte Dokument zu bezahlen.
Criteria length Enthält die Länge des nachfolgenden Suchkriteriums in Bytes.
Search criteria Ein im ISO-8859-1-Format kodierter String eines regulären Ausdrucks, der das gesuchte Dokument beschreibt.
Ein Servent darf nur dann auf eine Suchanfrage antworten, wenn er mindestens ein Dokument freigegeben hat,
das zum regulären Ausdruck der Suchanfrage passt und nicht mehr als der angegebene Betrag kostet. Ist dies
der Fall, erzeugt der Servent eine QueryHit-Nachricht, mit der MessageID der zugeh örigen Query-Nachricht.
Analog zum Pong wird das TTL-Feld mit dem Wert des Hops-Feldes der Query-Nachricht belegt und das
Hops-Feld auf 0 gesetzt. Der Nutzdatenbereich hat eine variable Länge und ist wie folgt aufgebaut:
1
#Hits
2
Port
4
IP Address
var.
Result Sets
#Hits Enthält die Anzahl der passenden Suchergebnisse, die in den folgenden Result Sets näher beschrieben
werden.
Port, IP Address Adresse des HTTP-Servers, der Anfragen nach den in den Result Sets beschriebenen Dokumenten entgegennimmt (siehe Abschnitt A.3).
Result Sets Enthält #Hits viele direkt aufeinander folgende Result Sets, die jeweils ein passendes Suchergebnis genauer beschreiben. Mit den Informationen aus einem Result Set ist der Empfänger in der Lage,
HTTP-Anfragen zum Herunterladen des beschriebenen Dokuments zu erzeugen. Ein Result Set hat den
folgenden Aufbau:
4
File index
4
File size
2
Price
1
FN length
var.
File name
File index Eine Nummer, die das Dokument innerhalb des anbietenden Servents eindeutig identifiziert.
File size Dateigröße in Bytes.
Price Mindespreis, der für das Dokument verlangt wird.
FN length Länge des nachfolgenden Dateinamens in Bytes.
File name Der im ISO-8859-1-Format kodierte Dateiname.
A.2
Routing
P2P-Netze können im Allgemeinen sehr dynamisch sein, d.h. Knoten treten dem Netzwerk bei oder bestehende Verbindungen werden getrennt. Anders als in relativ statischen Netzen wie beispielsweise dem Internet ist
Ralf Wienzek, [email protected]
20
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
der Aufbau und die Pflege von effizienten Routen in einem solchen Netzwerk aufw ändig. Zudem sollen einige Nachrichten wie z.B. Suchanfragen eine große Anzahl von Servents erreichen, um eine m öglichst große
Auswahl an Suchergebnissen zu haben.
Für das Routing von Nachrichten werden in Anlehnung an den Gnutella-Standard die folgenden Regeln definiert:
1. Ping-Nachrichten werden an alle direkt mit dem Servent verbundenen Servents weitergeleitet, mit Ausnahme desjenigen, von dem die Nachricht empfangen wurde. Dies geschieht aber nur, wenn nicht bereits
eine Ping-Nachricht mit identischer MessageID weitergeleitet worden ist. In diesem Fall wird die Nachricht verworfen.
Entsprechendes gilt für Query-Nachrichten.
2. Eine Pong-Nachricht wird nur an denjenigen Servent weitergeleitet, von dem die zugeh örige PingNachricht empfangen wurde (zu erkennen an der gleichen Message-ID). Sollte eine Pong-Nachricht
mit einer Message-ID empfangen werden, für die keine Ping-Nachricht weitergeleitet wurde, wird die
Pong-Nachricht verworfen.
Gleiches gilt für QueryHit- und zugehörigen Query-Nachrichten.
3. Das TTL-Feld von Ping- und Query-Nachrichten ist geeignet zu initialisieren. Als Standard soll der Wert
7 verwendet werden.
4. Vor dem Weiterleiten einer Nachricht, wird das TTL-Feld um 1 verringert und das Hops-Feld um 1
erhöht.
A.3
Download von Dokumenten
Durch eine QueryHit-Nachricht erhält ein Käufer alle benötigten Informationen, um ein gewünschtes Dokument von einem Verkäufer herunterzuladen. Der Käufer baut hierzu außerhalb des P2P-Netzes eine neue TCPVerbindung zum HTTP-Server des Verkäufers auf und teilt diesem mit, an welchem Dokument er interessiert
ist. Zur Beschreibung des gewünschten Dokuments wird auf eine angepasste Variante des HTTP-Protokolls
zurückgegriffen, das normalerweise zur Kommunikation zwischen Webbrowser und Webserver verwendet
wird. HTTP ist ein textbasiertes Protokoll, d.h. die folgenden Nachrichten werden als im ISO-8859-1-Format
kodierte Strings über die zuvor aufgebaute TCP-Verbindung übertragen.
Die Kommunikation beginnt mit folgender Anfrage des Käufers, der die Datei mit dem Index <File Index>
und dem Namen <File Name> zum Preis <Price> vom Server anfordert:
GET /get/<File Index>/<File Name>/ HTTP/1.0\n
Connection: close\n
Range: byte=0-\n
Price: <Price>\n
User-Agent: Gnutella\n
\n
Der HTTP-Server des Verkäufer-Servents überprüft, ob der Benutzer eine solche Datei freigegeben hat. Dabei
ist darauf zu achten, dass Index und Name mit der Freigabe übereinstimmen und der Preis nicht geringer als der
durch den Benutzer angegebene Mindestpreis ist. Existiert eine solche Datei auf dem Server, beginnt dieser mit
der Übertragung. Bevor jedoch die eigentliche Datei übertragen wird, übermittelt der Server zunächst einige
Kontrollinformationen, u.a. seine Bankverbindung. Direkt nachdem der Download erfolgreich beendet wurde,
Ralf Wienzek, [email protected]
21
Sommersemester 2005
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Softwarepraktikum
Netzwerkprogrammierung in Java
muss der Käufer den Betrag auf das angegebene Konto überweisen. Der Verkäufer teilt ihm hierzu die IPAdresse und Portnummer seiner Bank, seine Kontonummer und eine Rechnungsnummer mit. Die Rechnungsnummer ist bei der Überweisung als Überweisungszweck anzugeben und kann vom Verkäufer dazu verwendet
werden, eingehende Zahlungen getätigten Verkäufen zuzuordnen. Sie kann daher vom Verkäufer frei gewählt
werden.
HTTP 200 OK\n
Server: P2P-Market\n
Content-type: application/binary\n
Content-length: <File Size>\n
Price: <Price>\n
Account: <Account Number>\n
Bank: a.b.c.d:p\n
Invoice: <Invoice Number>\n
\n
Die Übertragung der Datei erfolgt unmittelbar im Anschluss und die TCP-Verbindung wird anschließend beendet.
Sollte die angeforderte Datei nicht existieren oder der Preis zu gering sein, sendet der Server eine Fehlermeldung.
HTTP 404 Not Found\n
Server: P2P-Market\n
\n
Ralf Wienzek, [email protected]
22
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
B Bankprotokoll
Im Folgenden werden die Funktionen eines P2P-Bank-Servers und das verwendete Kommunikationsprotokoll
beschrieben. Anders als Verbindungen zwischen Servents, die auch aufrecht erhalten werden, wenn aktuell keine Daten zum Versand anstehen, werden TCP-Verbindungen zur Bank beendet, sobald keine weiteren Auftr äge
mehr übertragen werden sollen. Die Verbindung wird vom Client beendet, sobald er vom Server die Antworten
auf sämtliche seiner Aufträge erhalten hat. Der Client darf mehrere Aufträge abschicken ohne auf die Antworten
der bereits gesendeten Aufträge warten zu müssen. Die Reihenfolge der Antworten muss nicht mit derjenigen
der Aufträge übereinstimmen. Um Antworten Aufträgen zuordnen zu können, erhält jeder Auftrag eine ID, die
in der entsprechenden Antwort ebenfalls enthalten ist.
• Kontoeröffnung: Für die Eröffnung eines Kontos wird vom Benutzer ein Passwort für den späteren Zugriff auf das Konto erwartet. Der Bankserver erstellt ein neues Konto, indem eine bisher von dieser Bank
noch nicht vergebene Kontonummer erzeugt und dem Antragsteller in der Antwortnachricht übermittelt wird. Des Weiteren wird das Konto mit einem Startkapital initialisiert, dessen H öhe durch die Bank
vorgegeben wird.
Nachrichtenformate:
Anfrage: Kunde → Bank
Größe:
Feld:
1
0x10
4
ID
1
LP
var.
Passwort
Das erste Byte enthält den Code (0x10 = 1610 ) und zeigt an, dass es sich um eine Anfrage zur Kontoeröffnung handelt. Um später eintreffende Antworten den entsprechenden Anfragen zuordnen zu k önnen,
vergibt der Sender eine für ihn eindeutige, 4 Byte große ID, welche der Bankserver in seiner Antwortnachricht wiederholt. Es folgt ein 1 Byte großes Feld, das die Länge des nachfolgenden in der Größe
variierenden Passwort-Feldes bestimmt.
Beispiel: 16 1
2
3
4
6
’s’ ’i’ ’c’ ’h’ ’e’ ’r’
Erfolg: Bank → Kunde
1
0x11
4
ID
4
KtoNr
4
Kontostand
Der Code 0x11 zeigt an, dass das Konto erfolgreich er öffnet wurde. Die ID ist dieselbe Zahl, die in der
Anfrage an den Server übermittelt wurde. Es folgt ein 4 Byte großes Feld, welches die Kontonummer des
frisch eröffneten Kontos als vorzeichenlose Zahl enthält. Im letzten Feld steht der initiale Kontostand als
vorzeichenbehaftete 32 Bit-Zahl.
Beispiel für eine Kontonummer von 1 und einem Kontostand von 1000:
17 1 2 3 4 0 0 0 1 0 0 3 232
Fehler: Bank → Kunde
1
0x12
4
ID
1
LT
var.
Fehlertext
Der Code 0x12 zeigt an, dass beim Versuch der Kontoer öffnung ein Fehler aufgetreten ist. ID entspricht
dem Wert aus der Anfrage. Es folgt ein Byte, welches die Länge des nachfolgenden Fehlertextes angibt.
Beispiel: 18 1
2
3
4
Ralf Wienzek, [email protected]
5
’E’ ’R’ ’R’ ’O’ ’R’
23
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
• Kontotest: Ein Kontoinhaber möchte testen, ob er noch Zugriff auf ein Konto hat, das er er öffnet, aber
eine Zeit lang nicht benutzt hat. Er übergibt hierzu Kontonummer und Passwort und der Bankserver
überprüft, ob ein solches Konto bei der Bank geführt wird. Treten Probleme beim Zugriff auf das Konto
auf, teilt die Bank dies dem Kunden über eine entsprechende Fehlernachricht mit.
Nachrichtenformate:
Anfrage: Kunde → Bank
1
0x20
4
ID
4
KtoNr
1
LP
var.
Passwort
Die ersten beiden Felder sind wie üblich definiert. Das dritte Feld enthält die Kontonummer des zu
überprüfenden Kontos. Die übrigen beiden Felder enthalten das Passwort bzw. dessen Länge.
Erfolg: Bank → Kunde
1
0x21
4
ID
Eine Bestätigung, dass der Zugriff auf das Konto möglich ist.
Fehler: Bank → Kunde
1
0x22
4
ID
1
LT
var.
Fehlertext
Siehe oben.
• Überweisung: Eine Überweisung transferiert einen bestimmten Betrag von einem Konto auf ein anderes.
Dabei muss das Empfängerkonto nicht notwendigerweise von der gleichen Bank gef ührt werden, wie
das zu belastende Konto. Anstelle der sonst üblichen Bankleitzahlen wird hier eine Kombination aus IPAdresse und Portnummer verwendet und dadurch eine Bank bzw. der Bankserver eindeutig identifiziert.
Nachrichtenformate:
Anfrage: Kunde → Bank
1
0x30
4
ID
4
BKtoNr
4
EIP
2
EPort
4
EKtoNr
4
Betrag
1
LP
1
LT
var.
Passwort
var.
ÜText
Das Feld BKtoNr enthält die Kontonummer des zu belastenden Kontos. Dieses muss bei der Bank gef ührt
werden, bei der die Überweisung eingereicht wird. Die Felder EIP und EPort enthalten die IP-Adresse
und die Portnummer der Empfängerbank und EKtoNr die Kontonummer des Empfängers. Der zu überweisende Betrag wird anschließend als vorzeichenlose 32-Bit-Zahl übertragen. Die 1 Byte großen Felder
LP und LT geben die Länge des Passworts bzw. des Überweisungstextes an.
Erfolg: Bank → Kunde
1
0x31
4
ID
Gibt an, dass der Auftrag von der Bank erfolgreich entgegengenommen wurde.
Fehler: Bank → Kunde
1
0x32
4
ID
1
LT
var.
Fehlertext
Siehe oben.
Ralf Wienzek, [email protected]
24
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
Sobald die Bank einen Überweisungsauftrag entgegengenommen hat, ist sie daf ür verantwortlich, dass
der Betrag dem Empfängerkonto gutgeschrieben wird. Wird das Empfängerkonto ebenfalls von dieser
Bank verwaltet, kann dies direkt durch eine interne Buchung geschehen. Ist das Empf ängerkonto jedoch
bei einer anderen Bank eröffnet worden, muss diese über die Überweisung informiert werden. Hierzu
wird eine weitere Nachricht definiert:
Bank → Bank:
1
4
4
0x38 ID BIP
2
BPort
4
BKtoNr
4
EKtoNr
4
Betrag
1
LT
var.
ÜText
BIP und BPort identifizieren die Bank, von der aus der Betrag überwiesen wurde (d.h. diejenige Bank, die
diese Nachricht sendet), und BKtoNr die Kontonummer des belasteten Kontos. EKtoNr ist die Nummer
des Empfängerkontos. Betrag, LT und ÜText haben die gleiche Bedeutung wie in der ursprünglichen
Nachricht.
Die Erfolgs- bzw. Fehlermeldungen sind analog zu denen der Original überweisung aufgebaut, jedoch
werden hier die Codes 0x39 und 0x3A statt 0x31 und 0x32 verwendet.
• Kontoauszug: Der Benutzer soll sich die letzten Transaktionen seines Kontos ansehen k önnen. Eine erfolgreiche Bearbeitung einer Kontoauszug-Anfrage liefert den aktuellen Kontostand und alle bisher noch
nicht abgefragten Umsätze zurück. Damit nur legitime Benutzer den Kontostand zu einer Kontonummer
abfragen können, wird das bei der Kontoeröffnung gewählte Passwort verlangt.
Nachrichtenformate:
Anfrage: Kunde → Bank
1
0x40
4
ID
4
KtoNr
1
LP
var.
Passwort
Die Kontonummer und das Passwort werden in der üblichen Weise an den Bankserver übertragen.
Erfolg: Bank → Kunde
1
0x41
4
ID
4
Kontostand
1
#Ums.
var.
Umsätze
Nach der Anfrage-ID wird der aktuelle Kontostand als vorzeichenbehaftete 32-Bit-Zahl übertragen. Das
darauf folgende Feld gibt an, wie viele Umsätze in dieser Nachricht hintereinander abgelegt sind. Jeder
Umsatz hat das folgende Format:
4
IP
2
Port
4
KtoNr.
4
Betrag
1
LT
var.
ÜText
Die ersten drei Felder eines jeden Umsatzes identifizieren das (fremde) Konto, von dem aus die Überweisung erfolgte bzw. auf das der Betrag überwiesen wurde. Das vierte Feld enthält eine vorzeichenbehaftete
32-Bit-Zahl, welche angibt, wie viel Geld auf das Konto, f ür das der Auszug angefordert wurde, überwiesen (positive Zahl) bzw. wie viel abgehoben wurde (negative Zahl). Die übrigen beiden Felder enthalten
den Überweisungstext und dessen Länge.
Fehler: Bank → Kunde
1
0x42
4
ID
1
LT
var.
Fehlertext
Siehe oben.
Ralf Wienzek, [email protected]
25
Sommersemester 2005
Softwarepraktikum
Netzwerkprogrammierung in Java
INFORMATIK 4
Communication Systems
Prof. Dr. O. Spaniol
• Kontoauflösung: Ein Kontoinhaber möchte sein Konto auflösen und übermittelt der Bank hierzu seine
Kontonummer und das zugehörige Passwort.
Nachrichtenformate:
Anfrage: Kunde → Bank
1
0x50
4
ID
4
KtoNr
1
LP
var.
Passwort
Die ersten beiden Felder sind wie üblich definiert. Das dritte Feld enthält die Kontonummer des Kontos,
das aufgelöst werden soll. Die übrigen beiden Felder enthalten das Passwort bzw. dessen Länge.
Erfolg: Bank → Kunde
1
0x51
4
ID
Eine Bestätigung, dass die Kontoauflösung mit der angegebenen ID erfolgreich ausgeführt wurde.
Fehler: Bank → Kunde
1
0x52
4
ID
1
LT
var.
Fehlertext
Siehe oben.
Ralf Wienzek, [email protected]
26
Sommersemester 2005