Verantwortlich:
Prof. Anja Feldmann,
Jörg Wallerich,
Vinay Aggarwal,
Dr. Manfred Jobmann,
Nils Kammenhuber,
Arne Wichmann
Letzte Änderung an dieser Seite:
Wir bemühen uns, in dieser FAQ folgende Kennzeichnung zu verwenden (nur in graphischen Browsern sichtbar):
![]() |
Punkt ist vor kurzem neu hinzugekommen |
![]() |
Punkt wurde vor kurzem wesentlich geändert |
![]() |
Punkt ist schon eine Zeitlang in der FAQ und wurde nicht mehr geändert (...oder einer von uns hat mal wieder vergessen, den Punkt als neu oder geändert zu markieren... ;-) ) |
print-Anweisungen
aus.
Am Lehrstuhl sind Transponderkarten erhältlich, die die Tür zum Praktikumsraum jederzeit öffnen können. Die Ausgabe der Karten erfolgt an die Praktikumsteilnehmer nachdem die Registrierung abgeschlossen ist.
Ansonsten geh' in den Flur des Lehrstuhl Feldmann und frag' irgendjemanden der Anwesenden, ob er/sie Dir mit seinem/ihrem Transponder den Praktikumsraum öffnen kann.
Sollte keiner mehr dort sein, bleibt Dir wohl nichts anderes übrig, als z.B. in die "Sunhalle" zugehen und Dich von dort aus remote einzuloggen.
Einfach mit ssh auf irgendeinen der folgenden Rechner einloggen:
viper.net.informatik.tu-muenchen.de slowworm.net.informatik.tu-muenchen.de housesnake.net.informatik.tu-muenchen.de seasnake.net.informatik.tu-muenchen.de adder.net.informatik.tu-muenchen.de cobra.net.informatik.tu-muenchen.de boa.net.informatik.tu-muenchen.de copperhead.net.informatik.tu-muenchen.de
Bis der password:-Prompt kommt, kann es u.U. eine Zeitlang dauern, also nicht die Geduld verlieren.
Wenn Du einen Laptop hast, kannst Du ihn einfach an eines der freien Ethernetkabel anschließen, die an den Switches auf den Praktikumstischen dranhängen und dann mit Deinem Laptop arbeiten. (Außerdem soll wohl in absehbarer Zeit das Funk-LAN im Gebäude funktionieren.)
Siehe auch Wie greife ich auf die Rechner im Praktikumsraum zu?
Die Lösungen müssen...
Angenommen, mein eigenes Login lautete meinLogin und das meines Teampartners partnerLogin. Die Uhrzeit sei 15:00h (und 27 Sekunden). Dann gebe ich meine Lösung für die 1. Übung folgendermaßen ab:
meinLogin@viper> mkdir meinLogin_partnerLogin
meinLogin@viper> cp loesungsfile1 loesungsfile2 loesungsfile3 usw meinLogin_partnerLogin/
meinLogin@viper> date +%H%M%S
150027
meinLogin@viper> tar -czf meinLogin_partnerLogin_150027.tgz meinLogin_partnerLogin/
meinLogin@viper> cp meinLogin_partnerLogin_150027.tgz /home/inetprak/abgabe/1.uebung/
meinLogin@viper> chmod g+r /home/inetprak/abgabe/1.uebung/meinLogin_partnerLogin_150027.tgz
meinLogin@viper>
Schon abgegebene Lösungen können bis zur Abgabedeadline upgedatet werden (d.h., man kann z.B. sicherheitshalber z.B. ein paar Tage vor der Deadline schonmal eine halbfertige Lösung abgeben, ohne Nachteile zu erwarten.) Dazu gibt man einfach nochmal eine komplette Lösung wie oben beschrieben mit aktuellem Datum ab.
Siehe auch Welche Sprachen sind erlaubt?
| Befehl | liefert |
|---|---|
| man perl | generelle Übersicht |
| man perlsyn | Syntax von Perl |
| man perlfunc | die in Perl eingebauten Funktionen |
| man perldata | Infos zu den Datentypen von Perl |
| man perlrun | u.A. trickreiche Parameter beim Aufruf von
Perl, die einem viel Schreibarbeit sparen können
(z.B. perl -n -a) |
| ... | ... |
| man perltoc | Übersicht über die anderen Manpages zum Thema Perl |
Sofern nicht genauer spezifiziert, sind folgende Sprachen erlaubt:
grep, sort,
cut,...) benutzen. In diesen Skripten dürfen auch
selbstgeschriebene Perl-, C-, C++ oder Java-Programme aufgerufen werden.
Beispielsweise wäre eine Kombination wiezcat datei.gz | java mein.tolles.Programm | ./meinperlskript | perl -n -e '...(mein Perl-Einzeiler...)' | sort
$CLASSPATH bei Java-Programmen, oder
Umleiten der Ausgabe Deines Programmes in einen Shellbefehl wie
z.B. sort, usw.), dann schreibe einfach ein kurzes
Shellskript, das diese Aufgaben automatisch erledigt.
Für das dritte Aufgabenblatt (und die weiteren Blätter) sind
Java und das Perl-Modul IO::Socket wieder erlaubt.
Beim RFC-Editor.
Angenommen, das Verzeichnis heiße dir. Dann:
Es ist ein mit dem Befehl gzip komprimiertes File. Zum Ausgeben auf Standardausgabe benutze entweder
In Perl kannst Du es recht trickreich auslesen mit
open(DATEIHANDLE, "zcat dateiname|")
so dass das File also beim Auslesen gleich automatisch dekomprimiert wird.
Du brauchst nicht immer ein Programm zu schreiben; Du kannst manchmal wichtige Informationen durch eine einzige Zeile in der Shell herausbekommen.
Benutze hierzu die sogenannten Pipes. Wenn z.B. der Inhalt der Datei zu groß ist, kannst Du die Ausgabe des Dekompressionskommandos in den Pager less pipen, und zwar mit zcat dateiname.gz | less.
Du kannst diese Pipes sogar schachteln, was sie sehr, sehr mächtig
macht. Ein Beispiel:
zcat name.gz | grep "http" | sort -n -r | uniq | head >ausgabe.txt
Wohlgemerkt: Das ist eine einzige Zeile, die man in die Shell eintippt. Diese recht komplexe Aufgabe wurde also komplett ohne irgendein Programm oder Skript gelöst.
zcat logfile.gz | perl -e 'while(<>){s/\s+/ /g;@l=split;@f=split("/",$l[3]);$p{$f[1]}++;}foreach $i (sort keys %p) {print "$i:$p{$i}\n";}'
Natürlich ist dieser Einzeiler schrecklich unübersichtlich und somit quasi unlesbar. Daher nochmal in kommentierter Form:
| zcat logfile.gz | Ausgabe des Logfiles auf die Standardausgabe (vgl. oben) |
| | | Umleiten von Standardausgabe auf Standardeingabe |
| perl -e | Aufruf von Perl mit der restlichen Kommandozeile als auszuführendes Skript |
| while() {} | While-Schleife |
| <> | Zeilenweises Lesen der Standardeingabe (in Variable
$_) |
| while(<>) {} | Durchlaufen aller Zeilen der Standardeingabe |
| s/\s+/ /g; | globales Ersetzen von mehreren Spaces durch ein Space |
| @l=split; | Aufspalten einer Zeile in ein Array namens l
mit dem Space als Trennzeichen |
| @f=split ("/", $l[3]); | Aufspalten des 4ten Wortes (Trennzeichen ist "/") |
| $p{$f[1]}; | Benutzt 2ten Eintrag von f als Hash in Hashtabelle
p |
| $p{$f[1]}++; | Automatisches Erhöhen des Wertes in der Hashtabelle |
| keys %p | Liste aller Hashes der Hashtabelle p
Hash := Hashkey |
| sort keys %p | Sortiere die obige Liste von Hashes |
| foreach $i (sort keys %p) {} | Für jeden Eintrag (der dann bei jedem Durchlauf
jeweils in der Variable i gespeichert wird)
in der sortierten Liste von Hashes |
| print "$i:$p{$i}\n"; | Gib den Wert von i und den Wert des Hashes
aus |
Und wie Du siehst, kann man Perl also auch "on-the-fly" benutzen, also ohne eine extra Skriptdatei anzulegen. Das ist natürlich recht unübersichtlich, also muss man solche "Einzeiler" dann gut dokumentieren.
Mehr Infos, wie man Perl trickreich aufrufen kann und sich dadurch eine Menge Schreibarbeit sparen kann, findest Du übrigens auf der Manpage man perlrun.
Damit ist gemeint, daß alle Werte durch ihren Logarithmus ersetzt werden sollen.
Für Netzwerkverhältnisse ist das ein kleines Logfile. Ihr werdet im Praktikum daher auch lernen, wie man mit solch großen Datenmengen umgeht (z.B. was man tut, wenn das zu analysierende File gar nicht komplett ins RAM reinpasst...).
Es ist also nicht bloße Schikane, sondern durchaus Praxisorientierung.Wer ein Internet-Praktikum macht, der sollte auch einmal "von Hand" mit Sockets umgegangen sein, d.h. die entsprechenden Systemaufrufe verwendet haben. Java oder auch das Perl-Modul IO::Socket abstrahieren den Umgang mit Sockets aber zu stark von der Systemebene. Daher sind sie für das zweite Aufgabenblatt ausnahmsweise nicht erlaubt.
Du musst nicht, wir empfehlen es Dir nur. Einer der zahlreichen positiven Aspekte von Perl ist dabei auch der, dass man schon mit nur wenigen Kenntnissen der Sprache sehr weit kommt. Perls Motto ist there's more than one way to do it, was man auch so interpretieren kann, dass man auch schon als Anfänger in Perl "alles" machen kann, nur dass eben ein Perl-Profi die Sachen z.T. schneller und eleganter hinbekommt.
In diesem Praktikum wirst Du Perl insbesondere gebrauchen können für:
Auch im Alltag wird Dir Perl später gute Dienste leisten. Übrigens sind viele sog. CGI-Skripte im WWW-Bereich in Perl geschrieben.
Stelle bitte zunächst sicher, dass in der Shellvariable
$PATH auch das Verzeichnis /usr/local/bin
(oder alternativ /usr/local/java oder
/usr/local/j2sdk1.3.1) enthalten ist. Ansonsten kann die
Shell java natürlich nicht ausführen.
Sollte das der Fall sein und Java aber trotzdem nicht ausführbar sein, dann schreib uns bitte eine Mail, damit wir es auf dem entsprechenden Rechner nachinstallieren können.
Solange wir uns nicht gerührt haben, kannst Du Dich (z.B. mit dem Kommando ssh) auf einem anderen der Schlangenrechner einloggen, auf dem Java installiert ist.
Das TO_SERVER-Filehandle des Sockets wird nicht automatisch
geflusht, wenn man mit print() hineinschreibt.
Verwende daher einfach send() statt print(),
dann brauchst Du Dich gar nicht um das Flushing zu kümmern.
Du kannst zwar
das Autoflush mit $|=1 (möglichst zu Beginn des
Programms) einschalten, aber das löst die Probleme nicht immer.
print-Anweisungen
aus.Dieses Problem hat die gleichen Ursachen wie das
Problem, dass die Daten nicht beim Server ankommen
und kann daher auch genauso umgangen werden, nämlich mit
$| = 1; am Programmanfang.
Auf Folie 29 (Senden / Empfangen von Daten) ist ein Fehler. Der recvaufruf liefert entweder die Adresse der Gegenseite oder einen leeren String zurück (z.B. bei tcp). Der leere String bewirkt dann allerdings, dass
or die("Can't receive: $!\n") den recv-Aufruf als fehlgeschlagen interpretiert.
Der richtige Aufruf müßte lauten:
defined(recv(CONNS, $data_read, $maxlen, $flags)) or die "Can't receive: $!\n";
Viele Datenquellen, mit denen man arbeitet, sind Textdateien. Zum Bearbeiten dieser Dateien gibt es eine ganze Reihe an Unix-Kommandos, mit denen man (ohne eine Zeile Perl zu schreiben) auch schon recht viel erledigen kann. Insbesondere zum Analysieren von Logfiles u.ä. kann es sinnvoll sein, sich folgende Kommandos und ihre Manpages genauer anzuschauen:
Darüberhinaus kann man sich auch kompliziertere Pipes mit Hilfe sogenannter
named Pipes (auch FIFOs genannt) bauen. Wenn einem beispielsweise
befehl1|befehl2|befehl3|... nicht ausreicht und man z.B. "mehrere Pipes
parallel" legen möchte, dann kann man sich eine named pipe anlegen.
Das ist sozusagen eine spezielle Datei, die [fast] keinen Platz auf der Platte
belegt, und mit der man Eingaben von einem schreibenden Prozess in einen lesenden
Prozess umleiten kann. Oder man stellt es sich so vor, dass man dem |-Symbol
einen Dateinamen verpasst und statt befehl1|befehl2 dann z.B. befehl1>meinepipe
und befehl2<meinepipe verwenden kann. Aber natürlich geht es auch viel
flexibler, da man die Pipes [fast] immer anstelle von Dateien einsetzen kann,
was manchmal sehr elegant sein kann. Ein Beispiel:
meinLogin@viper> mkfifo /tmp/meinefifo
Damit legst Du eine neue Pipe namens meinefifo im Verzeichnis /tmp an.
meinLogin@viper> ls > /tmp/meinefifo &
[1] 12345
Das & bewirkt, dass
der ls-Befehl im Hintergrund abläuft. Die Shell zeigt an, dass dieser
Hintergrundprozess die Prozessnummer
12345 erhalten hat. Das ls versucht jetzt, in die Fifo zu schreiben;
allerdings liest momentan niemand aus der Fifo, so dass das ls ersmtal blockiert wird.
meinLogin@viper> cat /tmp/meinefifo
bin Desktop Kruscht mail netzsaug src tmp (...und was sonst noch so im Homedir drin ist)
[1]+ Done ls >/tmp/meinefifo
meinLogin@viper>
Das cat hat aus der Fifo rausgelesen, und somit konnte das im Hintergrund wartende
ls terminieren, was die Shell auch anzeigt ("[1]+ Done ls...").
Mit solchen Fifo-Tricks kann man z.B. auch kompliziertere, verzweigte Pipelines bauen, in der Art von
befehl1 -o fifo | befehl2 | befehl3 | befehl4 -r fifo | befehl5oder man kann "Pipeline-Ringe bauen", z.B. so:
befehl1 < ringfifo | befehl2 | befehl3 | befehl 4 > ringfifo
Hinweis: Man kann Fifos allerdings nicht dazu benutzen, um auf einem Rechner in die Fifo reinzuschreiben und auf einem anderen Rechner daraus zu lesen! Dazu verwendet man i.A. TCP-Sockets.
Kaum zu glauben, aber wahr: Für das uralte Problem, wie man einen 16-bit-Wert (oder einen 32-bit-Wert) in zwei Bytes (bzw. vier Bytes) hintereinander im Speicher ablegt, existieren zwei verschiedene Standards, nämlich big endian und little endian.
Mehr Infos über endianness findest Du z.B. hier:
hexdump versucht (wenn es ohne Kommandozeilen-Optionen aufgerufen
wird) die byte order seiner Eingabe je nach Maschinenarchitektur so zu drehen,
dass es die Eingabe als 16-bit Werte interpretieren kann. Um bei der Anzeige
das zu sehen, was tatsaechlich in der Datei steht sollte man hexdump -c
(octal) oder besser hexdump -C (hexadezimal) benutzen. Dann
wird die Datei byte für byte ausgegeben, ohne als 16-bit oder gar als 32-bit
Wert interpretiert zu werden.
Weitere Informationen zu hexdump
findest du (wie für alle Unix-Tools) mit man hexdump.
NEIN! Mit "die Ausgabe soll ungefähr ... von dig entsprechen" ist gemeint, dass die Ausgabe eures Programmes die gleichen Informationen enthalten soll wie die von dig (Also einfach die Werte aller Felder, die im DNS Packet vorkommen). Ihr braucht natuerlich nicht das Ausgabeformat von dig exakt nachzubauen. (Wenn Ihr Spass daran habt koennt ihr das natürlich gerne tun...;-))
NEIN! Die zu erstellende Datei soll einen kompletten DNS-Request, also sowohl Header als auch die Queston-Section enthalten. Beide Teile sind für einen gütigen DNS-Request zwingend notwendig.
100 OPEN <client-id>
101 OPEN <server-id>Es ändert sich nur der Zahlencode zum Client-Server Handshake. Die
server-id ist analog zur client-id zu ermitteln.
Garnicht! Eine Nachricht an einen speziellen Empfänger zu senden ist bei Multicast nicht vorgesehen! Das wäre Unicast. Für Unicast müßte die Nachricht eine Zieladresse enthalten. Bei Multicast spezifiziert der Kanal nicht einen einzelnen, sondern eine ganze Gruppe von Empfängern.
Für BGP müssen Nachrichten zwar an einen bestimmten Peer gesandt werden. In diesem Fall ist der Peer aber immer ein direkter Nachbar und als solcher durch die TCP-Verbindung über die der Nachbar angeschlossen ist, eindeutig identifiziert (wie z.B. auch bei Handshake-Nachrichten)!
Ein existierender Routing-Algorithmus und eine Forwarding-Table sind allerdings notwendig, um Multicast
betreiben zu können. Wir werden im 9. Blatt die durch BGP aufgefüllte Forwarding-Table zur
Implementation von echtem Multicast benötigen
Die Aufgabe, ein komplett funktionierendes Multicast-System aufzubauen, ist relativ komplex, da es
aus einer ganzen Reihe nicht trivialer Einzelproblemen besteht. Diese Einzelprobleme (z.B. Forwarding Table)
sind jedoch isoliert lösbar, weshalb jedes dieser Teilprobleme auch als einzelne Aufgabe gestellt wird.
Angenommen, wir betrachten Prefix p und Peer A.
Dann sind die beiden mit **** markierten Zeilen ein Beispiel
für zwei "aufeinanderfolgende" Updates vom gleichen Peer zum selben
Prefix:
Zeit Peer Prefix ---------------- 1 B p 2 A p **** 3 A r 4 B r 5 B s 6 A p **** 7 C rMan kann sich auch den Update-Strom als das Ergebnis eines Multiplexer vorstellen, der die Updates für viele Peer-Prefix-Paare mischt. Um zwei aufeinanderfolgende Updates zu finden, muss man den Updatestrom wieder de-multiplexen.