20.6 Telnet – telnetlib 

Das Modul telnetlib ermöglicht die Verwendung des sogenannten Telnet-Netzwerkprotokolls (Teletype Network). Telnet wurde als möglichst einfaches bidirektionales Netzwerkprotokoll konzipiert. Häufig wird Telnet dazu verwendet, einen kommandozeilenbasierenden Zugriff auf einen entfernten Rechner zu ermöglichen. Da das Telnet-Protokoll aber keine Möglichkeit zur Verschlüsselung der übertragenen Daten bietet, wurde es nach und nach von anderen, in diesem Bereich stärkeren Protokollen wie beispielsweise SSH verdrängt.
Im Modul telnetlib ist im Wesentlichen die Klasse Telnet enthalten, über die die weitere Kommunikation mit dem entfernten Rechner abläuft. Der Konstruktor der Klasse Telnet hat die folgende Schnittstelle:
telnetlib.Telnet([host[, port]])
Erzeugt eine Instanz der Klasse Telnet. Optional können bereits hier der Hostname und der Port des Rechners übergeben werden, zu dem eine Verbindung hergestellt werden soll. Wenn keiner der Parameter angegeben wird, muss die erzeugte Telnet-Instanz explizit durch Aufruf der Methode open verbunden werden. Die Angabe einer Portnummer ist nur dann notwendig, wenn die Verbindung nicht über den Standardport 23 ablaufen soll.
Die Klasse Telnet
Nachdem sie erzeugt und mit dem Zielrechner verbunden wurde, kann eine Telnet-Instanz zur Kommunikation mit dem verbundenen Rechner verwendet werden. Dazu enthält sie eine Reihe Methoden, von denen die wichtigsten im Folgenden erläutert werden sollen. Dabei sei t eine Instanz der Klasse telnetlib.Telnet.
Generell gilt, dass, wenn während einer Lese- oder Schreiboperation die Verbindung geschlossen wird, eine IOError-Exception aus der gerade aktiven Methode heraus geworfen wird.
t.read_until(expected[, timeout])
Liest ankommende Daten, bis der String expected empfangen wurde. Alternativ kann ein Timeout in Sekunden als zweiter Parameter angegeben werden, nach dessen Ablaufen der Lesevorgang abgebrochen wird. Die gelesenen Daten werden als String zurückgegeben.
t.read_all()
Liest alle ankommenden Daten, bis die Verbindung geschlossen wird. Beachten Sie, dass diese Methode das Programm auch so lange blockiert. Die gelesenen Daten werden zurückgegeben.
t.open(host[, port])
Verbindet die Telnet-Instanz zum entfernten Rechner host unter Verwendung des Ports port. Diese Funktion sollte nur aufgerufen werden, wenn die Verbindungsdaten nicht bereits dem Konstruktor der Klasse Telnet übergeben wurden.
t.close()
Schließt die Telnet-Verbindung zum entfernten Rechner.
t.write(buffer)
Sendet den String buffer zum Verbindungspartner. Diese Funktion kann das Programm blockieren, wenn die Daten nicht sofort geschrieben werden können.
Beispiel
Im folgenden Beispielprogramm soll das Modul telnetlib dazu verwendet werden, zu einem POP3-Server zu verbinden. Dabei möchten wir auf die abstrahierte Schnittstelle des Moduls poplib verzichten und dem Server direkt POP3-Kommandos senden. Da das POP3-Protokoll jedoch relativ simpel ist und auf lesbaren Kommandos basiert, stellt dies kein großes Problem dar.
Das Ziel des Programms ist es, die Ausgabe des POP3-Kommandos LIST zu erhalten, das die Indizes aller im Posteingang liegenden Mails auflistet.
Im Programm soll die Telnet-Kommunikation möglichst komfortabel über eine auf POP3 zugeschnittene Klasse ablaufen:
import telnetlib
class POP3Telnet(object):
def __init__(self, host, port): self.tel = telnetlib.Telnet(host, port) self.lese_daten()
def close(self): self.tel.close()
def lese_daten(self): return self.tel.read_until(".\r\n", 20.0)
def kommando(self, kom): self.tel.write("%s\r\n" % kom) return self.lese_daten()
Dem Konstruktor der Klasse POP3Telnet werden Hostname und Port des POP3-Servers übergeben. Intern wird dann eine Instanz der Klasse Telnet erzeugt und mit diesem Server verbunden. Durch Aufruf der Methode lese_daten wird die Begrüßungsnachricht des Servers ausgelesen und verworfen, da sie nicht weiter von Interesse ist, aber bei späteren Lesevorgängen stören würde.
Wichtig sind die Methoden lese_daten und kommando. Die Methode lese_daten liest genau einen Antwortstring des POP3-Servers ein. Eine solche Antwort wird stets durch den String ".\r\n" beendet. Der gelesene String wird zurückgegeben. Damit dieser Lesevorgang das Programm bei einem unerreichbaren Server nicht auf unbestimmte Zeit blockiert, wurde ein Timeout von 20 Sekunden festgelegt.
Die zweite wichtige Methode ist kommando. Sie erlaubt es, einen POP3-Befehl an den Server zu senden. Dieser Befehl wird inklusive eines abschließenden "\r\n" in die Telnet-Instanz geschrieben und von dieser an den verbundenen Rechner weitergeleitet. Schlussendlich wird die Antwort des Servers eingelesen und zurückgegeben.
Doch die Klasse ist nur der erste Teil des Beispielprogramms. Im nun folgenden zweiten Teil wird die Klasse POP3Telnet zur Kommunikation mit einem POP3-Server eingesetzt. Dazu werden zunächst die Zugangsdaten für den POP3-Server festgelegt:
host = "pop.test.de" port = 110 user = "benutzername" passwd = "passwort"
Jetzt wird eine Instanz der Klasse POP3Telnet erzeugt, die mit dem angegebenen POP3-Server verbunden ist. Dann wird die Anmeldeprozedur durch Senden der Kommandos USER und PASS durchgeführt.
pop = POP3Telnet(host, port) pop.kommando("USER %s" % user) pop.kommando("PASS %s" % passwd)
An dieser Stelle sind wir, wenn bei der Anmeldung alles gut gelaufen ist, dazu in der Lage, mit beliebigen POP3-Kommandos auf den Posteingang zuzugreifen. Dann schicken wir das eingangs erwähnte LIST-Kommando. Das LIST-Kommando des POP3-Protokolls liefert eine Liste aller im Posteingang enthaltenen E–Mails. Jeder Eintrag besteht dabei aus dem ganzzahligen Index der jeweiligen E-Mail und ihrer Größe in Byte.
Beachten Sie, dass der Server auf LIST zwei Antwortstrings sendet, von denen uns nur der zweite interessiert, da dieser die Daten über vorhandene E-Mails enthält. Aus diesem Grund muss nach dem Aufruf der Methode kommando noch einmal der zweite Antwortstring eingelesen werden. Der zurückgegebene String wird ausgegeben. Im Code sieht das folgendermaßen aus:
pop.kommando("LIST")
print pop.lese_daten()
pop.kommando("QUIT")
pop.close()
Zum Schluss schicken wir das Kommando QUIT an den Server und schließen die Telnet-Verbindung. Die Ausgabe des Beispielprogramms könnte folgendermaßen aussehen:
1 623 2 614 3 1387 .
In diesem Fall befinden sich drei E-Mails mit den Größen 623, 614 und 1387 Byte im Posteingang.