Programmierung in Ruby

Der Leitfaden der Pragmatischen Programmierer

Netzwerk- und Web-Bibliotheken



Ruby stellt zwei Ebenen für den Zugang zu Netzwerkdiensten zur Verfügung. Auf niedriger Ebene kann auf die Socket-Unterstützung des zugrunde liegenden Betriebssystem zugegriffen werden, der die Einrichtung von Clients und Servern sowohl für verbindungs-orientierte wie auch für verbindungslose Protokolle erlaubt. Diese sind im folgenden Unterkapitel dokumentiert.

Ruby stellt auch Bibliotheken für den Zugriff auf höherer Ebene für spezifische Anwendungsprotokolle, wie z.B. FTP, HTTP, usw. zur Verfügung. Diese sind in einem weiteren Unterkapitel beschrieben.

Schließlich bieten die im dritten Unterkapitel dokumentierten CGI-Bibliotheken eine geeignete Schnittstelle für die Entwicklung von Web-Anwendungen auf der Server-Seite.

Socket-Level Access

Sockets stellen die Endpunkte eines bidirektionalen Kommunikationskanals dar. Sie können entweder innerhalb eines Prozesses, zwischen Prozessen auf einer Maschine oder zwischen Prozessen auf verschiedenen Kontinenten miteinander kommunizieren. Sockets werden über eine Reihe verschiedener Kanäle implementiert: Unix Domain Sockets, TCP, UDP, usw. Die Socket-Bibliothek stellt sowohl spezifische Klassen zur Verfügung, um die gängigen Transportkanäle zu bedienen wie auch eine generische Schnittstelle für den Rest. Alle Funktionen in der Socket-Bibliothek stehen in einer einzigen Erweiterungsbibliothek. Sie wird eingebunden mit

require 'socket'

Sockets haben ihr eigenes Vokabular:

Domain
Die Protokollfamilie, die für den Transport verwendet wird. Diese Werte sind Konstanten wie z.B. PF_INET, PF_UNIX, PF_X25, usw.
Typ
Der Typ der Kommunikation zwischen den Endpunkten. Typische Werte sind SOCK_STREAM für Verbindungs-orientierte und SOCK_DGRAM für verbindungslose Protokolle.
Protokoll
Typischerweise Null, jedoch kann dieser Parameter verwendet werden, um die Variante eines Protokolls innerhalb einer Domäne und eines Typs festzulegen.
hostName
Der Bezeichner für eine Netzwerkschnittstelle:
port
(manchmal auch service) Jeder Server lauscht an einem oder mehreren Ports nach Client-Aufrufen. Ein Port kann eine Fixnum-Portnummer, ein String mit einer Portnummer oder der Name eines Dienstes sein.

Alle Sockets sind Kinder der Klasse IO. Wenn ein Socket erfolgreich geöffnet wurde, können die konventionellen I/O-Methoden benutzt werden. Manchmal ist jedoch mit den Socket- spezifischen Methode eine höhere Effizienz möglich. Wie auch andere I/O-Klassen, werden standardmässig Blöcke gebildet. Die Rangfolge der Socket-Klassen ist in Abbildung 26.1 gezeigt.

Ausführlichere Dokumentation zur Benutzung von Sockets findet sich in der Dokumentation Ihres Betriebssystems. Eine umfassende Abhandlung findet sich auch in W. Richard Stevens, Unix Network Programming, Volumes 1 and 2 .

Hierarchie der Socket-Klassen

Figur 026.1 Hierarchie der Socket-Klassen

class BasicSocket
Parent: IO
Version: 1.6

Index:

do_not_reverse_lookup do_not_reverse_lookup= lookup_order lookup_order= close_read close_write getpeername getsockname getsockopt recv send setsockopt shutdown


BasicSocket ist eine abstrakte Basisklasse für alle übrigen Socket-Klassen.

Diese Klasse wie auch ihre Unterklassen manipulieren häufig Adressen indem sie etwas wie struct sockaddr benutzen, was tatsächlich ein undurchsichtiger Binärstring ist [In Wirklichkeit bildet dieser String ein struct sockaddr aus der darunter liegenden Sprache C ab, ein Satz von Strukturen, der in den man-Seiten und in den Büchern von Stevens dokumentiert ist.].

class methods
do_not_reverse_lookup BasicSocket.do_not_reverse_lookup -> true oder false

Gibt der Wert des global reverse lookup Flags zurück. Wenn dieser Wert true ist, geben Anfragen auf entfernte Adressen nur die numerische Adresse jedoch nicht den Hostnamen zurück.

do_not_reverse_lookup= BasicSocket.do_not_reverse_lookup = true oder false

Setzt das global reverse lookup Flag.

lookup_order BasicSocket.lookup_order -> eineFixnum

Gibt die Reihenfolge der globalen Adress-Suche an; folgende Werte sind möglich:

Folge Durchsuchte Familien
LOOKUP_UNSP AF_UNSPEC
LOOKUP_INET AF_INET, AF_INET6, AF_UNSPEC
LOOKUP_INET6 AF_INET6, AF_INET, AF_UNSPEC

lookup_order= BasicSocket.lookup_order = eineFixnum

Setzt die Reihenfolge der globalen Adress-Suche.

instance methods
close_read eineSession.close_read -> nil

Schließt eine Leseverbindung auf diesem Socket.

close_write eineSession.close_write -> nil

Schließt die Schreibverbindung auf diesem Socket.

getpeername eineSession.getpeername -> einString

Gibt die struct sockaddr-Struktur, die mit der Gegenstelle dieser Socket-Verbindung assoziiert ist, zurück.

getsockname eineSession.getsockname -> einString

Gibt die struct sockaddr-Struktur zurück, die mit eineSession assoziiert ist.

getsockopt eineSession.getsockopt( level, optName ) -> einString

Gibt den Wert der angegebenen Option zurück.

recv eineSession.recv( laenge, [, flags] ) -> einString

Empfängt bis zu laenge Bytes von eineSession.

send eineSession.send( einString, flags, [, to] ) -> eineFixnum

Sendet einString über eineSession. Wenn to angegeben ist, enthält es ein struct sockaddr, das die Empfangsadresse enthält. flags sind ein oder mehrere der MSG_-Optionen (aus der Liste der Klassenkonstanten von Socket). Gibt die Anzahl der gesendeten Zeichen zurück.

setsockopt eineSession.setsockopt( level, optName, optVal ) -> 0

Setzt eine Socket-Option. level is eine der Socket-Level-Optionen (aus der Liste der Klassenkonstanten von Socket). optname und optval sind Protokoll-spezifisch---siehe die Systemdokumentation für Details.

shutdown eineSession.shutdown( how=2 ) -> 0

Schaltet entweder den Empfangsteil (how == 0), den Sendeteil (how == 1) oder beide Teile (how == 2) dieser Socket-Verbindung ab.

class IPSocket
Parent: BasicSocket
Version: 1.6

Index:

getAdresse addr peeraddr


Die Klasse IPSocket ist eine Basisklasse für Sockets, die das IP als Transportebene einsetzen. TCPSocket und UDPSocket sind Ableitungen dieser Klasse.

class methods
getAdresse IPSocket.getAdresse( hostName ) -> einString

Gibt die vierstellige, punkt-getrennte IP-Adresse von hostName zurück.

a = IPSocket.getAdresse('www.ruby-lang.org')
a » "210.251.121.214"

instance methods
addr eineSession.addr -> einArray

Gibt den Domainname, den Port, den Namen und die IP-Adresse von eineSession in einem vier-Elemente-Array zurück. Der Name wird auch als Adresse angegeben, wenn das do_not_reverse_lookup-Flag den Wert true hat.

u = UDPSocket.new
u.bind('localhost', 8765)
u.addr » ["AF_INET", 8765, "localhost", "127.0.0.1"]
BasicSocket.do_not_reverse_lookup = true
u.addr » ["AF_INET", 8765, "127.0.0.1", "127.0.0.1"]

peeraddr eineSession.peeraddr -> einArray

Gibt den Domainnamen, den Port, den Namen und die IP-Adresse der Gegenstelle zurück.

class TCPSocket
Parent: IPSocket
Version: 1.6

Index:

gethostbyname new open recvfrom


t = TCPSocket.new('localhost', 'ftp')
t.gets » "220 zip.local.thomases.com FTP server (Version 6.2/OpenBSD/Linux-0.11) ready.\r\n"
t.close » nil

class methods
gethostbyname TCPSocket.gethostbyname( hostName ) -> einArray

Sucht nach hostName und gibt den kanonischen Namee, ein Array mit eventuellen Alias-Bezeichnugen, den Adresstyp (AF_INET) sowie die vierstellige IP-Adresse zurück.

a = TCPSocket.gethostbyname('ns.pragprog.com')
a » ["pragprog.com", [], 2, "63.68.129.131"]

new TCPSocket.new( hostName, port ) -> sock

Öffnet eine TCP-Verbindung zu hostName auf den angegebenen Port.

open TCPSocket.open( hostName, port ) -> sock

Synonym für TCPSocket.new.

instance methods
recvfrom eineSession.recvfrom( laenge[, flags] ) -> einArray

Empfängt bis zu laenge Bytes über die Verbindung. flags ist keine oder mehr der MSG_-Optionen (aus der Liste der Klassenvariablen von Socket). Gibt ein zwei-Elemente-Array zurück. Das erste Element enthält die empfangenen Daten, das zweite ist ein Array mit Informationen zur Gegenstelle.

t = TCPSocket.new('localhost', 'ftp')
data = t.recvfrom(30)
data » ["220 zip.local.thomases.com FTP", ["AF_INET", 21, "localhost", "127.0.0.1"]]

class SOCKSSocket
Parent: TCPSocket
Version: 1.6

Index:

new open close


Die Klasse SOCKSSocket unterstützt Verbindungen auf der Basis des SOCKS Protokolls.
class methods
new SOCKSSocket.new( hostName, port ) -> sock

Öffnet eine SOCKS-Verbindung zu port auf hostName.

open SOCKSSocket.open( hostName, port ) -> sock

Synonym für SOCKSSocket.new.

instance methods
close sock.close -> nil

Schließt diese SOCKS Verbindung.

class TCPServer
Parent: TCPSocket
Version: 1.6

Index:

new open accept


Eine TCPServer-Klasse empfängt ankommende TCP-Verbindungen. Hier kommt ein Webserver, der auf einem bestimmten Port lauscht und die Zeit zurückgibt.

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end

class methods
new TCPServer.new( [hostName,]port ) -> sock
Erstellt einen neuen Socket auf der angegebenen Schnittstelle (durch hostName und port identifiziert). Wenn hostName weggelassen wird, hört der Server alle Schnittstellen auf dem aktuellen Hostrechner ab (equivalent mit der Adresse 0.0.0.0).

open TCPServer.open( [hostName,]port ) -> sock

Synonym für TCPServer.new.

instance methods
accept eineSession.accept -> einTCPSocket

Wartet auf eine Verbindung eineSession, und gibt einen neuen TCPSocket zurück, der mit dem Aufrufer verbunden ist. Siehe das Beispiel auf Seite 478.

class UDPSocket
Parent: IPSocket
Version: 1.6

Index:

new open bind connect recvfrom send


UDP-Sockets senden und empfangen Datenpakete. Damit ein Socket Daten empfangen kann, muss er mit einem bestimmten Port verknüpft sein. Es gibt zwei Möglichkeiten, um Daten zu senden: Entweder wird auf einen remote-UDP-Socket verbunden und danach die Datenpakete auf diesen Port geschickt, oder es wird ein Hostrechner und Port angegeben, an den alle gesendeten Pakete gehen. Dieses Beispiel ist ein UDP-Server, der die empfangene Nachricht schreibt. Er wird sowohl von Verbindungs- orientierten wie auch von verbindungslosen Clients angesprochen.

require 'socket'

$port = 4321

sThread = Thread.start do     # run server in a thread   server = UDPSocket.open   server.bind(nil, $port)   2.times { p server.recvfrom(64) } end

# Ad-hoc client UDPSocket.open.send("ad hoc", 0, 'localhost', $port)

# Connection based client sock = UDPSocket.open sock.connect('localhost', $port) sock.send("connection-based", 0) sThread.join
ergibt:
["ad hoc", ["AF_INET", 1544, "localhost", "127.0.0.1"]]
["connection-based", ["AF_INET", 1545, "localhost", "127.0.0.1"]]

class methods
new UDPSocket.new( family = AF_INET ) -> sock

Erstellt einen Endpunkt für die UDP-Kommunikation, wobei optional die Adressfamilie angegeben wird.

open UDPSocket.open( family = AF_INET ) -> sock

Synonym für UDPSocket.new.

instance methods
bind eineSession.bind( hostName, port ) -> 0

Assoziiert das lokale Ende der UDP-Verbindung mit hostName und port. Diese Methode muss von Servern genutzt werden, um einen ansprechbaren Endpunkt zu etablieren.

connect eineSession.connect( hostName, port ) -> 0

Erstellt eine Verbindung zu einem gegebenen hostName und port. Darauf folgende UDPSocket#send-Anfragen, die den Client nicht überschreiben, nutzen diese Verbindung. Es können mehrere connect-Anfragne innerhalb eineSession gestellt werden: die jeweils letzte wird von send genutzt.

recvfrom eineSession.recvfrom( laenge[, flags] ) -> einArray

Empfängt bis zu laenge Bytes von eineSession. flags is keine oder mehr der MSG_-Optionen (aus der Liste der Klassenvariablen in Socket). Das Ergebnis ist ein zwei-Elemente-Array, das die empfangenen Daten sowie Informationen zum Absender enthält. Siehe auch das oben gezeigte Beispiel.

send eineSession.send( einString, flags ) -> eineFixnum
eineSession.send( einString, flags, hostName, port ) -> eineFixnum

Die zwei-Parameter-Form sendet einString auf einen bestehenden Verbindung. Die vier-Parameter-Form sendet einString an port auf hostName.

class UNIXSocket
Parent: BasicSocket
Version: 1.6

Index:

new open addr path peeraddr recvfrom


Die Klasse UNIXSocket unterstützt die Interprozess-Kommunikation mit Hilfe des Unix-Domain-Protokolls. Obwohl das zugrunde liegende Protokoll sowohl Paket- wie auch Stream-Verbindungen erlaubt, stellt die Ruby-Bibliothek lediglich die Stream-basierte Verbindung zur Verfügung.

require 'socket'

$path = "/tmp/sample"

sThread = Thread.start do        # run server in a thread   sock = UNIXServer.open($path)   s1 = sock.accept   p s1.recvfrom(124) end

client = UNIXSocket.open($path) client.send("hello", 0) client.close

sThread.join
ergibt:
["hello", ["AF_UNIX", ""]]

class methods
new UNIXSocket.new( pfad ) -> sock

Eröffnet einen neuen Domain-Socket auf pfad, der ein gültiger Pfadname sein muss.

open UNIXSocket.open( pfad ) -> sock

Synonym für UNIXSocket.new.

instance methods
addr eineSession.addr -> einArray

Gibt die Adressfamilie und den Pfad dieses Sockets zurück.

path eineSession.path -> einString

Gibt den Pfad dieses Domain-Sockets zurück.

peeraddr eineSession.peeraddr -> einArray

Gibt die Adressfamilie und den Pfad der Gegenstelle zurück.

recvfrom eineSession.recvfrom( laenge[, flags] ) -> einArray

Empfängt bis zu laenge Bytes von eineSession. Dabei enthält flags keine oder mehr der MSG_-Optionen (aus der Liste der Klassenvariablen von Socket) Das erste Element des zurückgegebenen Arrays enthält die empfangenen Daten, das zweite enthält Informationen über den Absender.

class UNIXServer
Parent: UNIXSocket
Version: 1.6

Index:

new open accept


Die Klasse UNIXServer stellt einen einfachen Unix Domain-Socket Server bereit. Siehe UNIXSocket für ein Code-Beispiel.

class methods
new UNIXServer.new( pfad ) -> sock

Erstellt einen neuen Server auf dem angegebenen pfad. Die korrespondierende Datei darf zum Zeitpunkt des Aufrufs nicht exisiteren.

open UNIXServer.open( pfad ) -> sock

Synonym für UNIXServer.new.

instance methods
accept eineSession.accept -> einUnixSocket

Wartet auf eine Verbindung zum Server-Socket und gibt ein neues Socket-Objekt für diese Verbindung zurück. Siehe auch das Beispiel für einen UNIXSocket weiter oben.

class Socket
Parent: BasicSocket
Version: 1.6

Index:

for_fd getaddrinfo gethostbyaddr gethostbyname gethostname getnameinfo getservbyname new open pair socketpair accept bind connect listen recvfrom


Die Klasse Socket ermöglicht den Zugriff auf die zugrunde liegende Socket-Implementierung. Sie kann verwendet werden, um eher Betriebssystem-spezifische Funktionen anzubieten als die Protokoll-spezifischen Socket-Klassen. Dies muss mit höherer Komplexität bezahlt werden. Insbesondere werden Adressen mit Hilfe der struct sockaddr-Struktur, die in Ruby-Strings verpackt ist, behandelt, deren Manipulation eine spezielle Freude sein kann.

Konstanten

Socket definiert Konstanten für die Verwendung innerhalb der gesamten Socket-Bibliothek. Die jeweiligen Konstanten stehen nur auf Architekturen zur Verfügung, die die entsprechende Funktion unterstützen.

Socket-Typen:

SOCK_DGRAM, SOCK_PACKET, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM.

Protokollfamilien:

PF_APPLETALK, PF_AX25, PF_INET6, PF_INET, PF_IPX, PF_UNIX, PF_UNSPEC.

Adressfamilien:

AF_APPLETALK, AF_AX25, AF_INET6, AF_INET, AF_IPX, AF_UNIX, AF_UNSPEC.

Optionen zur Suchreihenfolge:

LOOKUP_INET6, LOOKUP_INET, LOOKUP_UNSPEC.

Sende-/Empfangsoptionen:

MSG_DONTROUTE, MSG_OOB, MSG_PEEK.

Optionen auf Socket-Ebene:

SOL_ATALK, SOL_AX25, SOL_IPX, SOL_IP, SOL_SOCKET, SOL_TCP, SOL_UDP.

Socket-Optionen:

SO_BROADCAST, SO_DEBUG, SO_DONTROUTE, SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_NO_CHECK, SO_OOBINLINE, SO_PRIORITY, SO_RCVBUF, SO_REUSEADDR, SO_SNDBUF, SO_TYPE.

QOS-Optionen:

SOPRI_BACKGROUND, SOPRI_INTERACTIVE, SOPRI_NORMAL.

Multicast-Optionen:

IP_ADD_MEMBERSHIP, IP_DEFAULT_MULTICAST_LOOP, IP_DEFAULT_MULTICAST_TTL, IP_MAX_MEMBERSHIPS, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL.

TCP-Optionen:

TCP_MAXSEG, TCP_NODELAY.

getaddrinfo Fehlercodes:

EAI_ADDRFAMILY, EAI_AGAIN, EAI_BADFLAGS, EAI_BADHINTS, EAI_FAIL, EAI_FAMILY, EAI_MAX, EAI_MEMORY, EAI_NODATA, EAI_NONAME, EAI_PROTOCOL, EAI_SERVICE, EAI_SOCKTYPE, EAI_SYSTEM.

ai_flags Werte:

AI_ALL, AI_CANONNAME, AI_MASK, AI_NUMERICHOST, AI_PASSIVE, AI_V4MAPPED_CFG.

class methods
for_fd Socket.for_fd( einFD ) -> sock

Verpackt einen bereits geöffneten Datei-Deskriptor in ein Socket-Objekt.

getaddrinfo Socket.getaddrinfo( hostName, port,
[family[socktype[protokoll[flags]]]] ) -> einArray

Gibt ein Array von Arrays zurück, die den angegebenen Hostrechner und Port (optional noch wie gezeigt detaillierter spezifiziert) beschreiben. Jedes Unterarray enthält die Adressfamilie, die Portnummer, den Hostnamen, die Host-IP-Adresse, die Protokollfamilie, den Socket-Typ sowie das Protokoll.

for line in Socket.getaddrinfo('www.microsoft.com', 'http')
  puts line.join(", ")
end
ergibt:
AF_INET, 80, microsoft.net, 207.46.130.149, 2, 1, 6
AF_INET, 80, microsoft.net, 207.46.131.137, 2, 1, 6
AF_INET, 80, microsoft.com, 207.46.230.218, 2, 1, 6
AF_INET, 80, microsoft.com, 207.46.230.219, 2, 1, 6
AF_INET, 80, microsoft.net, 207.46.130.14, 2, 1, 6

gethostbyaddr Socket.gethostbyaddr( addr, type=AF_INET ) -> einArray
Gibt den Hostnamen, die Adressfamilie und die sockaddr-Komponente für die angegebene Adresse zurück.

a = Socket.gethostbyname("63.68.129.130")
res = Socket.gethostbyaddr(a[3], a[2])
res.join(', ') » "somewhere.in.pragprog.com, , 2, ?D\201\202"

gethostbyname Socket.gethostbyname( hostName ) -> einArray

Gibt ein vier-Elemente-Array mit dem kanonischen Hostnamen, einem Subarray mit den Host-Aliasnamen, der Adressfamilie und dem Adress-Teil der sockaddr-Struktur zurück.

a = Socket.gethostbyname("63.68.129.130")
a.join(', ') » "somewhere.in.pragprog.com, , 2, ?D\201\202"

gethostname eineSession.gethostname -> einString

Gibt den Namen des akutellen Hostrechners zurück.

getnameinfo Socket.getnameinfo( addr[, flags] ) -> einArray

Sucht nach der angegebenen Adresse, die entweder ein String mit einer sockaddr-Struktur oder ein drei- bzw. vier-Element-Array ist. Wenn addr ein Array ist, sollte es den Adressfamilien-String, den Port (oder nil) sowie den Hostnamen oder die IP-Adresse enthalten. Wenn ein viertes Element angegeben (und nicht nil) ist, wird es als Hostname verwendet. Die Methode gibt den kanonischen Hostnamen (oder die Adresse) und die Portnummer in einem Array zurück.

a = Socket.getnameinfo(["AF_INET", '23', 'www.ruby-lang.org'])
a » ["helium.ruby-lang.org", "telnet"]

getservbyname Socket.getservbyname( dienst, protokoll='tcp' ) -> eineFixnum

Gibt die Portnummer für den angegebenen Dienst und das entsprechende Protokoll zurück.

Socket.getservbyname("telnet") » 23

new Socket.new( domain, typ, protokoll ) -> sock

Erstellt einen Socket mit den angegebenen Parametern.

open Socket.open( domain, type, protokoll ) -> sock

Synonym für Socket.new.

pair Socket.pair( domain, typ, protokoll ) -> einArray

Gibt ein Paar verbundener, anonymer Sockets mit der angegebenen Spezifikation zurück.

socketpair Socket.socketpair( domain, typ, protokoll ) -> einArray

Synonym für Socket.pair.

instance methods
accept eineSession.accept -> einArray

Akzeptiert eine ankommende Verbindung und gibt ein Array mit einem neuen Socket-Objekt sowie einem String mit der struct sockaddr-Information über den Aufrufer zurück.

bind eineSession.bind( sockaddr ) -> 0

Bindet den Socket an die angegebene struct sockaddr, die in einem String enthalten sein muss.

connect eineSession.connect( sockaddr ) -> 0

Verbindet mit der angegebenen struct sockaddr, die in einem String enthalten sein muss.

listen eineSession.listen( eineFixnum ) -> 0

Horcht auf Verbindungen, wobei die angegebene eineFixnum als Überhang benutzt wird.

recvfrom eineSession.recvfrom( laenge[, flags] ) -> einArray

Empfängt bis zu laenge Bytes von eineSession. flags ist dabei keine oder mehr der MSG_-Optionen. Das erste Element des Ergebnisses sind die erhaltenen Daten. Das zweie Element enthält die Protkoll-spezifischen Informationen über den Absender.

Higher-Level Access

Ruby stellt einen Satz von Klassen zur Verfügung, die das Schreiben von Clients für bestimmte Protokolle erleichtern:

HTTP, POP und SMTP sind auf einer Helferklasse aufgesetzt, lib/net/protocol. Obwohl wir die Protocol hier nicht dokumentieren, sollten Sie sie genauer ansehen, wenn Sie einen eigenen Netzwerk-Client planen.

class Net::FTP
Parent: Object
Version: 1.6

Index:

new open Server commands close closed? connect debug_mode debug_mode= dir getbinaryfile gettextfile lastresp list login ls mtime passive passive= putbinaryfile puttextfile resume resume= retrbinary retrlines return_code storbinary storlines welcome


require 'net/ftp'

ftp = Net::FTP.new('ftp.netlab.co.jp') ftp.login files = ftp.chdir('pub/lang/ruby/contrib') files = ftp.list('n*') ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024) ftp.close

Die net/ftp Bibliothek implementiert einen File-Transfer-Protokoll (FTP) Client.

Konstanten
FTP_PORT Standardport für FTP-Verbindungen (21).

class methods
new FTP.new( host=nil, user=nil, passwd=nil, acct=nil) -> sock

Erstellt ein neues FTP-Objekt und gibt es zurück. Wenn der host-Parameter nicht nil ist, wird eine Verbindung zu diesem Hostrechner hergestellt. Zusätzlich werden die angegebenen Login-Informationen verwendet, wenn der user-Parameter nicht nil ist. Siehe auch die Beschreibung unter FTP#login.

open FTP.open( host, user=nil, passwd=nil, acct=nil) -> sock

Synonym für FTP.new, jedoch ist der host-Parameter zwingend erforderlich.

instance methods
Server commands ftp.acct( account )
ftp.chdir( dir )
ftp.delete( remoteFile )
ftp.mdtm( remoteFile ) -> einString
ftp.mkdir( dir )
ftp.nlst( dir=nil ) -> einArray
ftp.rename( fromname, toname )
ftp.rmdir( dir )
ftp.pwd -> einString
ftp.size( remoteFile ) -> anInteger
ftp.status -> einString
ftp.system -> einString

Setzt das entsprechende Server-Kommando ab und gibt das Ergebnis zurück.

close eineSession.close

Schließt die aktuelle Verbindung.

closed? eineSession.closed? -> true oder false

Gibt true zurück, wenn die aktuelle Verbindung bereits geschlossen ist.

connect ftp.connect( host, port=FTP_PORT )

Eröffnet eine FTP-Verbindung nach host, wobei der Standardport überschrieben werden kann. Wenn die Umgebungsvariable SOCKS_SERVER gesetzt ist, wird die Verbindung über einen SOCKS-Proxy geleitet. Die Methode wirft einen Fehler (typischerweise Errno::ECONNREFUSED) wenn die Verbindung nicht hergestellt werden kann.

debug_mode eineSession.debug_mode -> true oder false

Gibt den aktuellen Debug-Modus zurück.

debug_mode= eineSession.debug_mode = true oder false

Wenn der Debug-Modus true ist, wird der gesamte Verkehr vom und zum aktuellen Server auch auf $stdout ausgegeben.

dir eineSession.dir( [pattern]* ) -> einArray
eineSession.dir( [pattern]* ) {| line | block }

Synonym für FTP#list.

getbinaryfile eineSession.getbinaryfile( entfernteDatei, lokaleDatei, blockGroesse, callback=nil)
eineSession.getbinaryfile( entfernteDatei, lokaleDatei, blockGroesse ) {| data | block }

Empfängt entfernteDatei im Binärmodus und legt das Ergebnis in lokaleDatei. ab. Falls callback oder ein assoziierter Codeblock angegeben ist, werden die empfangenen Daten in blockGroesse großen Stücken dorthin weitergegeben.

gettextfile ftp.gettextfile( entfernteDatei, lokaleDatei, callback=nil)
ftp.gettextfile( entfernteDatei, lokaleDatei ) {| data | block }

Empfängt entfernteDatei im ASCII- (Text-) Modus und legt das Ergebnis in lokaleDatei ab. Wenn callback oder ein assoziierter Codeblock angegeben ist, werden die empfangenen Daten zeilenweise dorthin weitergegeben.

lastresp ftp.lastresp -> einString

Gibt die letzte Antwort des Hostrechners zurück.

list ftp.list( [muster]* ) -> einArray
eineSession.list( [pattern]* ) {| line | block }

Holt eine Liste der Dateien im Verzeichnis, das dem/den angegebenen Muster/n entspricht. Wenn mit dem Aufruf ein Codeblock assoziiert ist, wird jede Zeile des Ergebnisses dorthin weitergegeben. Anderenfalls wird das Ergebnis als ein Array von Strings zurückgegeben.

login ftp.login( user="anonymous", passwd=nil, acct=nil ) -> einString

Loggt sich am Hostrechner ein. ftp muss zuvor mit einem Hostrechner verbunden worden sein. Wenn als user der String ``anonymous'' sowie als Passwort nil angegeben ist, wird ein Passwort aus [email protected] generiert. Wenn der acct-Parameter nicht nil ist, wird nach dem erfolgreichen Login ein FTP-ACCT Kommando abgesetzt. Die Methode wirft typischerweise einen Net::FTPPermError, wenn Fehler auftreten.

ls ftp.ls( [pattern]* ) -> einArray
eineSession.ls( [pattern]* ) {| line | block }

Synonym für FTP#list.

mtime ftp.mtime( entfernteDatei, local=false ) -> eineZeit

Gibt die Zeit der letzten Änderung von entfernteDatei zurück, wobei die Antwort des Servers als GMT-Zeitangabe interpretiert wird, wenn local auf false gesetzt ist bzw. anderenfalls als lokale Zeit.

passive ftp.passive -> true oder false

Gibt den Status des passive-Flags zurück.

passive= ftp.passive = true oder false

Setzt die Verbindung in den passiven Modus, wenn true angegeben ist.

putbinaryfile eineSession.putbinaryfile( lokaleDatei, entfernteDatei, blockGroesse, callback=nil)
eineSession.putbinaryfile( lokaleDatei, entfernteDatei, blockGroesse ) {| data | block }

Überträgt lokaleDatei im Binärmodus zum Server, wobei das Ergebnis in entfernteDatei abgelegt wird. Wenn callback oder ein assoziierter Codeblock angegeben ist, werden die übertragenen Daten in Stücken von blockGroesse dorthin weitergegeben.

puttextfile ftp.puttextfile( lokaleDatei, entfernteDatei, callback=nil)
ftp.puttextfile( lokaleDatei, entfernteDatei ) {| data | block }

Überträgt lokaleDatei im ASCII- (Text-) Modus auf den Server und legt das Ergebnis in entfernteDatei ab. Wenn callback oder ein assoziierter Codeblock angegeben ist, werden die übertragenen Daten zeilenweise weiter gegeben.

resume ftp.resume -> true oder false

Gibt den Status des resume-Flags zurück (siehe FTP#resume=). Die Voreinstellung ist false.

resume= ftp.resume=einBoolean

Setzt den Status des resume-Flags. Wenn resumetrue gesetzt ist, nehmen teilweise übertragene Dateien die Übertragung an dem Punkt wieder auf, an dem sie unterbrochen wurde, anstatt sie wieder vom Dateianfang zu beginnen. Dies wird über das Absetzen des REST-Kommandos (RESTart unvöllständigen Transfer) an den Server.

retrbinary ftp.retrbinary( cmd, blockGroesse ) {| data | block }

Setzt die Verbindung in den Binärmodus (Bild-Modus), setzt das angegebene Kommando ab und holt die zurückgegebenen Daten ab, die in Stücken von blockGroesse Zeichen an den assoziierten Codeblock weitergereicht werden. Beachte: cmd ist ein Server-Kommando (wie z.B. ``RETR myfile'').

retrlines ftp.retrlines(cmd) {| line | block }

Setzt die Verbindung in den ASCII- (Text-) Modus, setzt das angegebene Kommando ab und gibt die zurückgegebenen Daten zeilenweise an den assoziierten Codeblock weiter. Wenn kein Codeblock angegebene ist, werden die Zeilen ausgegeben. Beachte: cmd ist ein Server-Kommande (wie z.B. ``RETR myfile'').

return_code ftp.return_code -> eineFixnum

Gibt den Rückgabewert (``return code'') der letzten Operation zurück.

storbinary ftp.storbinary( cmd, dateiName, blockGroesse, callback=nil)
ftp.storbinary( cmd, dateiName, blockGroesse ) {| data | block }

Setzt die Verbindung in den Binärmodus (Bildmodus), setzt das gegebene Server-Kommando (z.B. ``STOR myfile'') ab und schickt den Inhalt der Datei dateiName an den Server. Wenn der optionale Codeblock angegeben ist oder der callBack-Parameter ein Proc ist, werden die Daten in Stücken von blockGroesse Zeichen auch dorthin weitergegeben.

storlines ftp.storlines( cmd, dateiName, callback=nil)
ftp.storlines( cmd, dateiName ) {| data | block }

Setzt die Verbindung in den ASCII- (Text-) Modus, setzt das gegebene Server-Kommando (z.B. ``STOR myfile'') ab und schickt den Inhalt der Datei dateiName an den Server. Wenn callback auf eine Proc zeigt oder der optionale Codeblock angegeben ist, werden die Daten auch zeilenweise dorthin weitergegeben.

welcome ftp.welcome -> einString

Gibt die Begrüßungsnachricht des Servers zurück.

class Net::HTTP
Parent: Net::Protocol
Version: 1.6

Index:

new port start get head post start


require 'net/http'

h = Net::HTTP.new('www.pragmaticprogrammer.com', 80) resp, data = h.get('/index.html', nil ) puts "Code = #{resp.code}" puts "Message = #{resp.message}" resp.each {|key, val| printf "%-14s = %-40.40s\n", key, val } p data[0..55]
ergibt:
Code = 200
Message = OK
content-type   = text/html
last-modified  = Wed, 21 Feb 2001 18:52:26 GMT
date           = Mon, 05 Mar 2001 05:26:29 GMT
connection     = close
accept-ranges  = bytes
etag           = "804d98-1a4b-3a940e6a"
content-length = 6731
server         = Rapidsite/Apa-1.3.4 FrontPage/4.0.4.3
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional"

Die net/http Bibliothek stellt einen einfachen Client zur Verfügung, der Header und Web-Inhalte über das HTTP-Protokoll abholt.

get-, post- und head-Requests werfen bei jedem Fehler Exceptions (inklusive einiger HTTP-Statusantworten, die normalerweise als wiederherstellbar gelten würden). Es gibt zwei Möglichkeiten, diese zu behandeln.

  1. Jede Methode hat einen weitere Version get2, post2 oder head2, die keine Exception werfen. Diese Versionen sind in den Quelltexten dokumentiert.
  2. Wiederherstellbare Fehler werfen einen Net::ProtoRetriableError. Diese Exception enthält ein data-Attribut, das die vom Server übermittelte Antwort enthält.

Der untenstehende Code illustriert, wie ein HTTP-Status 301, eine Weiterleitung, gehandhabt wird. Er verwendet Tomoyuki Kosimizu's URI-Paket, das im RAA erhältlich ist.

h = Net::HTTP.new(ARGV[0] || 'www.ruby-lang.org', 80)
url = ARGV[1] || '/'

begin   resp, data = h.get(url, nil) { |a| } rescue Net::ProtoRetriableError => detail   head = detail.data

  if head.code == "301"     uri = URI.create(head['location'])

    host = uri['host']     url  = uri['path']     port = uri['port']

    h.finish     h = Net::HTTP.new(host, port)

    retry   end end

class methods
new Net::HTTP.new( host='localhost', port=80, proxy=nil, proxy_port=nil ) -> http

Erstellt ein neues HTTP-Objekt und gibt es zurück. Es wird bis zum Aufruf von HTTP#start keine Verbindung aufgebaut.

port Net::HTTP.port -> eineFixnum

Gibt den Standard-HTTP-Port (80) zurück.

start Net::HTTP.start( host=nil, port=80 )
Net::HTTP.start( host=nil, port=80 ) {| http | block }

Equivalent mit Net::HTTP.new(host, port).start.

instance methods
get http.get( pfad, header=nil, dest="" ) -> einArray
http.get( pfad, header=nil) {| result | block }

-> einArray

Empfängt Header und Inhalte aus dem angegebenen pfad auf dem Hostrechner, der bei der Erstellung von http angegeben wurde. Wenn der header-Parameter angegeben wird, muss er ein Hash mit zusätzlichen Header-Namen und -Werten sein, die mit der Anfrage gesendet werden sollen. Die Methode gibt eine zwei-Element-Array zurück. Das erste Element ist ein HTTPResponse-Objekt (das im nächsten Unterabschnit dokumentiert ist). Das zweite Element ist der Inhalt der Seite. Der Seiteninhalt wird auch an die <<-Methode des dest-Parameters bzw. an den Codeblock weitergegeben, sofern dieser angegeben ist. Dessen Ergebnis wird nicht zeilenweise, sondern Netzwerk-Block-weise ermittelt. Eine Exception wird geworfen, wenn ein Fehler auftritt. Auf http können mehrere Aufrufe von get erfolgen. Wenn nicht Protocol#finish ausdrücklich aufgerufen wird, nutzt die Verbindung das HTTP/1.1 Keep-Alive-Protokoll und schaltet zwischen den Anfragen nicht ab.

head http.head( pfad, header=nil ) -> einHash

Holt Header aus dem angegebenen pfad auf dem Hostrechner, der bei der Erstellung von http angegeben war. Wenn der header-Parameter angegeben wird, muss er ein Hash mit zusätzlichen Header-Namen und -Werten sein, der mit der Anfrage geschickt wird. Eine Exception wird geworfen, wenn ein Fehler auftritt. Auf einem http können mehrere Aufrufe von head erfolgen.

post http.post( pfad, daten, header=nil, dest="" ) -> einArray
http.post( pfad, daten, headers=nil ) {| result | block }-> einArray

Schickt eine HTTP POST-Anfrage mit daten an pfad. header ist ein hash mit zusätzlichen Headern. Das Ergebnis wird dem Parameter data oder dem Codeblock zugewiesen, wie bei Net_HTTP#get. Die Methode gibt ein zwei-Elemente-Array mit dem HTTPResponse-Objekt sowie dem Antwort-Teil zurück.

start http.start
http.start {| http | block }

Setzt eine Verbindung zu dem mit http assoziierten Hostrechner auf (start ist eigentlich eine Methode aus Net::Protocol, aber sie muss in HTTP-Objekten benutzt werden). In der Blockform wird die Session nach dem Ende des Blocks geschlossen.

class Net::HTTPResponse
Parent:
Version: 1.6

Index:

[ ] [ ]= code each key? message


Diese Klasse bildet eine HTTP-Antwort auf eine GET- oder POST-Anfrage ab.

instance methods
[ ] resp[ einSchluessel ] -> einString

Gibt die Header-Information zum übergebenen Schlüsselwort zurück. Die Groß-/Kleinschreibung im Schlüsselwort wird ignoriert. Z.B. wird auf das Schlüsselwort ``Content-type'' der Wert ``text/html'' zurückgegeben.

[ ]= resp[ einSchluessel ] = einString

Setzt die Header-Information zum angegebenen Schlüsselwort. Die Groß-/Kleinschreibung im Schlüsselwort wird ignoriert.

code resp.code -> einString

Gibt den Ergebniscode für die Anfrage zurück (z.B. ``404'').

each resp.each {| key, val | block }

Iteriert durch alle Header Schlüsselwort-Werte-Paare.

key? resp.key?( aKey ) -> true oder false

Gibt nur dann true zurück, wenn eine Header-Information mit dem angegebenen Schlüsselwort exisitert.

message resp.message -> einString

Gibt den Ergebnis-Text der Anfrage zurück (z.B. ``Not found'').

class Net::POP
Parent: Net::Protocol
Version: 1.6

Index:

new each finish mails start


require 'net/pop'
pop = Net::POP3.new('server.ruby-stuff.com')
pop.start('user', 'secret') do |pop|
  msg = pop.mails[0]

  # Print the 'From:' header line   puts msg.header.split("\r\n").grep(/^From: /)

  # Put message to $stdout (by calling <<)   puts "\nFull message:\n"   msg.all($stdout) end
ergibt:
From: Dave Thomas <[email protected]>

Full message: Return-Path: <[email protected]> Received: (from [email protected]) by pragmaticprogrammer.com (8.8.7/8.8.7) id XAA10537; Sun, 21 May 2000 23:45:58 -0500 Date: Sun, 21 May 2000 23:45:58 -0500 From: Dave Thomas <[email protected]> Message-Id: <[email protected]> To: [email protected] Subject: New Ruby Version Status: RO

Just to let you know there's a new Ruby version out.

Die net/pop-Bibliothek stellt einen einfachen Client zum abholen und versenden von Mail über einen Post-Office-Protokoll- (POP-) Server zur Verfügung.

Die Klasse Net::POP3 wird für den Zugriff auf einen POP-Server verwendet, wobie ein Liste von Net::POPMail-Objekten zurückgegeben wird, je eine pro Mail auf dem Server. Diese POPMail-Objekte werden dann verwendet, um die einzelnen Nachrichten abzuholen oder zu löschen. Die Bibliothek stellt auch eine Alternative zur POP3-Klasse zur Verfügung, die eine APOP-Authentifizierung durchführt.

class methods
new POP3.new( host='localhost', port=110 ) -> pop

Erstellt ein neues POP3-Objekt und gibt es zurück. Es wird keine Verbindung aufgebaut bevor POP3#start aufgerufen wird.

instance methods
each pop.each {| popmail | block }

Ruft den zugehörigen Codeblock einmal für jede e-Mail auf dem Server auf und gibt dabei das jeweilige POPMail-Objekt als Argument weiter.

finish pop.finish -> true oder false

Schließt die POP-Verbindung. Einige Server verlangen, dass die Verbindung geschlossen wird, bevor Aktionen wie z.B. das Löschen von Mail ausgeführt werden. Die Methode gibt false zurück, wenn die Verbindung nie benutzt wurde.

mails pop.mails -> einArray

Gibt ein Array mit POPMail-Objekten zurück, wobei jedes Objekt mit einer e-Mail Nachricht auf dem Server korrespondiert.

start pop.start( user, password )
pop.start( user, password ) {| pop | block }

Die Methode etabliert eine Verbindung zum POP-Server wobei die übergebenen Login-Informationen verwendet werden. Sie holt eine Liste von Mails auf dem Server ab, auf die mit Hilfe der POP3#mails- und POP3#each-Methoden zugegriffen werden kann. In der Block-Form wird pop an den Codeblock weitergegeben; nach der Ausführung des Blocks wird die Verbindung mit finish geschlossen.

class Net::APOP
Parent: Net::POP3
Version: 1.6

Index:

start


instance methods
start apop.start( user, password )

Die Methode etabliert eine Verbindung zum APOP-Server.

class Net::POPMail
Parent: Object
Version: 1.6

Index:

all delete delete! header size top uidl


instance methods
all mail.all -> einString
mail.all( ziel )
mail.all {| einString | block }

Holt die entsprechende e-Mail beim Server ab. Wenn kein Argument oder Codeblock angegeben wird, wird die e-Mail als String zurückgegeben. Mit einem Argument (kein Codeblock) wird die e-Mail an dest durch den Aufruf von dest<< für jede Zeile in der e-Mail weitergegeben. Mit einem zugehörigen Codeblock wird der Block für jede Zeile in der e-Mail aufgerufen.

delete mail.delete

Löscht die e-Mail vom Server.

delete! mail.delete!

Synonym für POPMail#delete.

header mail.header -> einString

Gibt die Header-Zeilen für die entsprechende e-Mail zurück.

size mail.size -> eineFixnum

Gibt die Größe der korrespondierenden e-Mail in Bytes zurück.

top mail.top( lines ) -> einString

Gibt die Header-Zeilen plus lines weitere Zeilen aus der korrespondierenden e-Mail Nachricht zurück.

uidl mail.uidl -> einString

Gibt den Server-spezifischen eindeutigen Bezeichner für die korrespondierende e-Mail zurück.

class Net::SMTP
Parent: Net::Protocol
Version: 1.6

Index:

new start ready sendmail start


require 'net/smtp'

# --- Send using class methods msg = [ "Subject: Test\n", "\n", "Now is the time\n" ] Net::SMTP.start do |smtp|   smtp.sendmail( msg,  [email protected]', ['dave'] ) end

# --- Send using SMTP object and an adaptor smtp = Net::SMTP.new smtp.start('pragprog.com') smtp.ready([email protected]', 'dave') do |a|   a.write "Subject: Test1\r\n"   a.write "\r\n"   a.write "And so is this" end

Die net/smtp-Bibliothek stellt einen einfachen Client zur Versendung von elektronischer Post mit Hilfe des Simple-Mail-Transfer-Protokolls (SMTP) zur Verfügung.
class methods
new Net::SMTP.new( server='localhost', port=25 ) -> smtp

Erstellt ein neues SMTP-Objekt, das mit dem angegebenen Server und Port verbunden ist, und gibt es zurück.

start Net::SMTP.start( server='localhost', port=25, domain=ENV['HOSTNAME'], acct=nil, passwd=nil, authtype=:cram_md5 ) -> smtp
Net::SMTP.start( server='localhost', port=25, domain=ENV['HOSTNAME'], acct=nil, passwd=nil, authtype=:cram_md5 ) {| smtp | block }

Equivalent mit Net::SMTP.new(server,port).start(...). Für eine Erläuterung der verbleibenden Parameter siehe die Instanzmethode Net_SMTP#start. Die Methode erstellt ein neues SMTP-Objekt. Der domain-Parameter wird für die anfängliche HELO- oder EHLO-Transaktion mit dem SMTP-Server verwendet. In der Blockform wird das smtp-Objekt an den Codeblock weitergegeben und die Sitzung wird geschlossen, wenn der Code-Block beendet wird.

instance methods
ready smtp.ready( from, to ) {| einAdapter | block }

Equivalent mit sendmail(from, to) { ...}. Schickt Header- und Inhaltszeilen an den sendmail-Server. Der from-Parameter wird als Absendername im MAIL FROM:-Kommando verwendet und der to-Parameter ist entweder ein String oder ein Array von Strings mit den Empfängern für das RCPT TO:-Kommando. Der Block erhält ein Adapter-Objekt. Der Server erhält Zeilen werden mit Hilfe der write-Methode des Adapters an den Server übermittelt. Der abschließende '.' und QUIT werden automatisch geschickt.

sendmail smtp.sendmail( src, from, to )

Schickt Header- und Inhaltszeilen an den sendmail-Server. Der from-Parameter wird als Absendername für das MAIL FROM:-Kommando verwendet und der to-Parameter ist entweder ein String oder ein Array von Strings mit den Empfängern für das RCPT TO:-Kommando. Die zu übermittelnden Zeilen werden mit dem Aufruf von src.each geholt. Der abschließende '.' und QUIT werden automatisch geschickt.

start smtp.start( domain=ENV['HOSTNAME'], acct=nil, passwd=nil, authtype=:cram_md5 ) -> true oder false
smtp.start( domain=ENV['HOSTNAME'], acct=nil, passwd=nil, authtype=:cram_md5 ) {| smtp | block }-> true oder false

Beginnt eine SMTP-Session indem eine Verbindung zur angegebenen Domain (Hostrechner) hergestellt wird. Wenn acct und passwd angegeben sind, wird die Authentifizierung mit dem angegebene Authentifizierungstyp (:plain oder :cram_md5) versucht. Wenn ein Codeblock angegeben ist, wird dieser mit smtp als Parameter aufgerufen. Die Verbindung wird geschlossen, wenn der Codeblock endet.

class Net::Telnet
Parent: [Socket]
Version: 1.6

Index:

new binmode binmode= cmd login print telnetmode telnetmode= waitfor write


Verbinde mit localhost, setze das ``date''-Kommando ab und trenne die Verbindung.

require 'net/telnet'
tn = Net::Telnet.new({})
tn.login "guest", "secret"
tn.cmd "date" » "date\r\nSun Mar  4 23:26:41 CST 2001\n\r> "

Überwache die auftretende Ausgabe. Wir assoziieren einen Block mit jedem Funktionsaufruf; dieser Codeblock wird immer aufgerufen, wenn Daten von Hostrechner vorliegen.

require 'net/telnet'

tn = Net::Telnet.new({})     { |str| print str } tn.login("guest", "secret")  { |str| print str } tn.cmd("date")  { |str| print str }
ergibt:
Trying localhost...
Connected to localhost.
Welcome to SuSE Linux 6.2 (i386) - Kernel 2.2.10-smp (pts/12).
login: guest
Password:
Last login: Sun Mar  4 23:26:41 from localhost

> date
Sun Mar  4 23:26:42 CST 2001

>

Hole die Zeitangabe von einem NTP-Server.

require 'net/telnet'
tn = Net::Telnet.new('Host'       => 'time.nonexistent.org',
                     'Port'       => 'time',
                     'Timeout'    => 60,
                     'Telnetmode' => false)
atomicTime = tn.recv(4).unpack('N')[0]
puts "Atomic time: " + Time.at(atomicTime - 2208988800).to_s
puts "Local time:  " + Time.now.to_s
ergibt:
Atomic time: Sun Mar 04 23:26:34 CST 2001
Local time:  Sun Mar 04 23:26:43 CST 2001

Die net/telnet-Bibliothek stellt eine komplette Implementierung eines Telnet-Clients dar und schließt Eigenschaften ein, die sie auch für nicht-Telnet-Dienste zu einem geeigneten Werkzeug machen.

Obwohl die folgende Klassenbeschreibung darauf hinweist, dass Net::Telnet eine Unterklasse von Socket ist, ist dies nicht wahr. In Wirklichkeit delegiert die Klasse an Socket. Der Effekt ist derselbe: Die Methoden von Socket und seiner Oberklasse IO sind durch Objekte vom Typ Net::Telnet verfügbar.

Die Methoden new, cmd, login und waitfor akzeptieren einen optionalen Codeblock. Wenn dieser angegeben ist, wird die Ausgabe des Servers wie empfangen an den Codeblock weitergereicht. Dies kann genutzt werden, um die Ausgabe in Echtzeit weiterzureichen anstatt z.B. einen Login abzuwarten bis die Antwort des Servers gezeigt wird.

class methods
new Net::Telnet.new( options ) -> tn
Net::Telnet.new( options ) {| str | block }-> tn

Verbindet mit einem Server. options ist ein Hash mit keinem oder mehreren der folgenden Optionen:

Option Standardwert Bedeutung
Binmode false Wenn true, werden keine end-of-line-Aktionen unterstützt.
Host localhost Name oder Adresse des Hostrechners auf dem der Service läuft.
Port 23 Name oder Nummer des aufzurufenden Service'.
Prompt /[$%#>]/ Ein Muster, das dem Prompt der Hostrechners entspricht.
Telnetmode true Wenn false, werden die meisten der Telnet-eigenen ESC-Sequenzen ignoriert. Wird verwendet, wenn mit einem nicht-Telnet-Server gesprochen wird.
Timeout 10 Zeit in Sekunden, die auf eine Antwort des Servers gewartet wird (während der Verbindung wie auch während der Datenübertragung).
Waittime 0 Zeit, die auf den Prompt im empfangenen Datenstrom gewartet wird.

instance methods
binmode tn.binmode -> true oder false

Gibt den aktuellen Wert des Binmode-Flags zurück.

binmode= tn.binmode = true oder false

Setzt das Binmode-Flag und gibt den neuen Wert zurück.

cmd tn.cmd( options ) -> einString
tn.cmd( options ) {| str | block }-> einString

Schickt einen String an den Server und wartet (unter Verwendung des Timeouts) auf einen String, der dem vom Server zurückzugebenden Muster entspricht. Wenn der Parameter kein Hash ist, wird er als String an den Server übermittelt und als erwartetes Muster sowie Timeout-Zeit werden die Werte Prompt und Timeout verwendet, die als Option bei der Erstellung von tn übergeben wurden. Wenn options vom Typ Hash ist, wird options['String'] an den Server geschickt. options['Match'] kann gesetzt werden, um das erwartete Muster zu überschreiben und in options['Timeout'] kann ein abweichender Timeout-Wert vorgegeben werden. Die Methode gibt die vollständige Antwort des Servers zurück.

login tn.login( options, password=nil ) -> einString
tn.login( options, password=nil ) {| str | block }-> einString

Wenn options vom Typ Hash ist, wird der Benutzername von options['Name'] und ein Passwort aus options['Password'] verwendet; anderenfalls wird angenommen, dass options der Benutzername ist und password das Passwort enthält. Die Methode wartet darauf, dass der Server einen String der Form /login[:[visible space]]*\z/ sowie den Benutzernamen zurücksendet. Wenn ein Passwort angegeben ist, wartet sie auch darauf, dass ein String der Form /Password[:[visible space]]*\z/ eintrifft, bevor das Passwort übermittelt wird. Die Methode gibt die vollständige Antwort des Server zurück.

print tn.print( einString )

Schickt einString an den Server, wobei Telnetmode, Binarymode bzw. jegliche zusätzlichen Modi, die mit dem Server ausgemacht wurden, berücksichtigt werden.

telnetmode tn.telnetmode -> true oder false

Gibt den aktuellen Wert des Telnetmode-Flags zurück.

telnetmode= tn.telnetmode= true oder false

Setzt das Telnetmode-Flag, wobei der neue Wert zurückgegeben wird.

waitfor tn.waitfor( options ) -> einString
tn.waitfor( options ) {| str | block }-> einString

Wartet darauf, dass der Server mit einem String antwortet, der mit einem String oder Muster übereinstimmt. Wenn options nicht vom Typ Hash ist, wird mit Hilfe von options.=== mit der gesamten Server-Ausgabe wie erhalten verglichen. Es ist wahrscheinlich, dass in diesem Fall ein regulärer Ausdruck verwendet wird.

Wenn options dagegen vom Tyo Hash ist, wird mit options['Match'], options['Prompt'] oder options['String'] verglichen. In letzterem Fall wird der String vor der Verwendung in einen regulären Ausdruck umgewandelt. options kann ebenso die Werte für ``Timeout'' und ``Waittime'' übergeben, um die Attribute der Klasse zu überschreiben.

write tn.write( einString )

Übergibt einString ohne weitere Übersetzung an den Server.

CGI Development

class CGI
Parent: Object
Version: 1.6

Index:

escape escapeElement escapeHTML new parse pretty rfc1123_date unescape unescapeElement unescapeHTML [ ] cookies has_key? header keys out params


require "cgi"
cgi = CGI.new("html3")  # add HTML generation methods
cgi.out {
  CGI.pretty (
    cgi.html {
      cgi.head { cgi.title{"TITLE"} } +
      cgi.body {
        cgi.form {
          cgi.textarea("get_text") +
          cgi.br +
          cgi.submit
        } +
        cgi.h1 { "This is big!" } +
        cgi.center { "Jazz Greats of the 20" +
          cgi.small {"th"} + " century" + cgi.hr
        } + cgi.p + cgi.table ('BORDER' => '5') {
          cgi.tr { cgi.td {"Artist"} + cgi.td {"Album"} } +
          cgi.tr { cgi.td {"Davis, Miles"} +
          cgi.td {"Kind of Blue"} }
        }
      }
    }
  ) # CGI.pretty is a method call, not a block
}

(Die Ausgabe dieses Skripts ist in Abbildung 26.2 wiedergegeben)

Die CGI-Klasse unterstützt Programme, die als Webserver CGI- (Common Gateway Interface) Skripte verwendet werden. Sie enthält einige Methoden, um auf Felder in einem CGI-Formular zuzugreifen, ``Cookies'' oder die Umgebung zu manipulieren sowie formatierte HTML-Quellen auszugeben.

Umgebungsvariablen enthalten viele nützliche Informationen für CGI-Skripte, daher vereinfacht CGI den Zugriff darauf---Umgebungsvariablen sind als Attribute von CGI-Objekten ansprechbar. Zum Beispiel gibt cgi.auth_type den Wert von ENV["AUTH_TYPE"] zurück. Für die Namensgebung wird der Variablenname komplett in Kleinbuchstaben übersetzt und das ``HTTP_''-Präfix weggelassen. Also stünde HTTP_USER_AGENT als Methode user_agent zur Verfügung stehen.

Cookies werden in einem separaten Objekt CGI::Cookie gehalten, das die folgenden Zugriffsmethoden besitzt:
Methode Beschreibung
name Name dieses Cookies
value Array mit den Werten des Cookies
path Pfad (optional)
domain Domäne (optional)
expires Verfallszeitpunkt, Standardwert ist Time.now (optional)
secure Ist für ein sicheres Cookie true

Output des CGI-Beispiel-Codes

Figur 026.2 Output des CGI-Beispiel-Codes

Ein Cookie wird erstellt, indem CGI_Cookie.new aufgerufen wird, die entweder die oben gezeigten Methodennamen als Argumente akzeptiert, bzw. indem CGI_Cookie.parse ein codierter String übergeben wird. Beide Methoden geben ein neues Cookie-Objekt zurück.

class methods
escape CGI.escape( einString ) -> einNeuerString

Gibt einen URL-codierten String zurück, der aus dem übergebenen Argument erstellt wird, wobei unsichere Zeichen (nicht alpha-numerische, ``_'', ``-'', oder ``.'') in ``%xx''-Escape Ausdrücke umgewandelt werden.

escapeElement CGI.escapeElement( einString[, elemente]* ) -> einNeuerString

Gibt einen aus dem angegebenen Argument erstellten String zurück, der einige HTML-Elemente umcodiert. Die in elemente angegebenen Elemente werden verändert; andere HTML-Elemente bleiben unberührt.

print CGI::escapeElement('<BR><A HREF="url"></A><P>', "A", "IMG")
ergibt:
<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;<P>

escapeHTML CGI.escapeHTML( einString ) -> einNeuerString

Gibt einen aus dem übergebenen Argument erzeugten String zurück, in dem spezielle HTML-Zeichen (wie z.B. ``&'',``"'',``<'',``>'') in ``&amp;'', ``&quot;'', ``&lt;'', ``&gt;'' usw. umcodiert wurden.

new CGI.new( [einString]* ) -> cgi

Gibt ein neues CGI-Objekt zurück. Wenn eine HTML-Ausgabe erwünscht ist, muss der gewünschte Standardlevel in einString übergeben werden, sonst werden keine Ausgabe-Routinen erstellt. Der Level ist einer der folgenden:

String Standardlevel String Standardlevel
``html3'' HTML 3.2 ``html4'' HTML 4.0 Strict
``html4Tr'' HTML 4.0 Transitional ``html4Fr'' HTML 4.0 Frameset

parse CGI.parse( einString ) -> einHash

Durchsucht einen String und gibt ein Hash mit den gefundenen Schlüssel-Wert-Paaren zurück.

pretty CGI.pretty( einHTMLString, anfuehrenderString=" " ) -> cgi

Formatiert einHTMLString in ein gut lesbares Format, wobei jede Zeile mit anfuehrenderString begonnen wird.

rfc1123_date CGI.rfc1123_date( einZeit ) -> einString

Gibt einen String zurück, der die angegebene Zeit in einem RFC1123-konformen Format enthält (for instance, Mon, 1 Jan 2001 00:00:00 GMT).

unescape CGI.unescape( einString ) -> einNeuerString

Gibt einen String zurück, der ``unsichere'' Zeichen im übergebenen URL-codierten Argument, in dem diese durch eine ``%''-Escape-Sequenz ersetzt waren, entcodiert enthält.

unescapeElement CGI.unescapeElement( einString[, elemente]* ) -> einNeuerString

Gibt einen String zurück, in dem die angegebenen ersetzten HTML-elemente wieder in die ursprünglichen Zeichen umgewandelt wurden.

unescapeHTML CGI.unescapeHTML( einString ) -> einNeuerString

Gibt einen String zurück, in dem alle zuvor codierten HTML-Elemente wieder in die ursprünglichen Zeichen umgewandelt wurden.

instance methods
[ ] cgi[ [einString]+ ] -> einArray

Gibt die Werte der angegebenen Feldnamen eines CGI-Formulars in einem Array zurück. Vgl. die Notiz zu mehrteiligen Formularen weiter unten.

cookies cgi.cookies -> einHash

Gibt ein neues Hash-Objekt mit den Schlüssel-Werte-Paaren der Cookies zurück.

has_key? cgi.has_key( einString ) -> true oder false

Gibt true zurück, wenn das Formular ein Feld enthält, das wie einString heisst.

header cgi.header( einContentTyp="text/html" ) -> einString
cgi.header( einHash ) -> einString

Gibt einen String mit den angegebenen Header-Werten zurück (in der MOD_RUBY-Umgebung wird stattdessen der entsprechende Header sofort verschickt). Wenn ein Hash als Argument angegeben ist, werden alle Schlüssel-Werte-Paare in entsprechende Header-Informationen umgesetzt.

keys cgi.keys -> einArray

Gibt ein Array mit allen im Formular definierten Feldnamen zurück.

out cgi.out( einContentTyp="text/html" ) { block }-> nil
cgi.out( einHash ) { block }-> nil

Erstellt eine HTML-Ausgabe aus dem Ergebnis des Codeblocks. Header werden wie in CGI#header beschrieben erstellt. Vgl. das Beispiel am Anfang dieses Kapitels.

params cgi.params -> einHash

Gibt ein neues Hash-Objekt mit Schlüssel-Werte-Paaren der Felder im HTML-Formular zurück.

HTML-Ausgabemethoden

Zusätzlich unterstützt CGI die folgenden HTML-Ausgabemethoden. Jede dieser Methoden ist nach dem korrespondierenden HTML-Element benannt (oder sehr dicht dran). Diejenigen Tags, die Inhalte erfordern (wie z.B. blockquote) akzeptieren einen optionalen Block; dieser sollte einen String zurückgeben, der dann als Inhalt für das jeweilige Element verwendet wird. Alle Methoden akzeptieren Argumente sowohl wie angegeben oder auch als Hash mit den angegebenen Namen als Schlüssel.

\

a( url )
a( HREF => )


base( url )
base( HREF => )


blockquote( cite="" ) { einString }
blockquote( CITE => ) { einString }


caption( align=nil ) { einString }
caption( ALIGN => ) { einString }


checkbox( name=nil, value=nil, checked=nil )
checkbox( NAME, VALUE, CHECKED => )


checkbox_group( name=nil, [items]+ )
checkbox_group( NAME, VALUES => )

Elemente können einzelne String-Namen sein oder auch: ein Array mit [ namechecked ], ein Array mit [ wertname ], oder ein Array mit [ wertnamechecked ]. Der Wert für den Hash-Schlüssel VALUES sollte ein Array mit diesen Elementen sein.


file_field( name="", size=20, maxlength=nil )
file_field( NAME, SIZE, MAXLENGTH => )


form( method="post", action=nil, enctype="application/x-www-form-urlencoded" ) { aStr }
form( METHOD, ACTION, ENCTYPE => ) { aStr }


hidden( name="", value=nil )
hidden( NAME, VALUE => )


html( ) { einString }
html( PRETTY, DOCTYPE => ) { einString }


img_button( src="", name=nil, alt=nil )
img_button( SRC, NAME, ALT => )


img( src="", alt="", width=nil, height=nil )
img( SRC, ALT, WIDTH, HEIGHT => )


multipart_form( action=nil, enctype="multipart/form-data" ) { einString }
multipart_form( METHOD, ACTION, ENCTYPE => ) { einString }


password_field( name="", value=nil, size=40, maxlength=nil )
password_field( NAME, VALUE, SIZE, MAXLENGTH => )


popup_menu( name="", items )
popup_menu( NAME, SIZE, MULTIPLE, VALUES(array of items) => )

Elemente können einzelne String-Namen sein oder auch: ein Array mit [ namechecked ], ein Array mit [ wertname ], oder ein Array mit [ wertnamechecked ]. Der Wert für den Hash-Schlüssel VALUES sollte ein Array mit diesen Elementen sein.


radio_button( name="", value=nil, checked=nil )
radio_button( NAME, VALUE, CHECKED => )


radio_group( name="", items )
radio_group( NAME, VALUES(array of items) => )

Elemente können einzelne String-Namen sein oder auch: ein Array mit [ namechecked ], ein Array mit [ wertname ], oder ein Array mit [ wertnamechecked ]. Der Wert für den Hash-Schlüssel VALUES sollte ein Array mit diesen Elementen sein.


reset( value=nil, name=nil )
reset( VALUE, NAME => )


scrolling_list( alias for popup_menu )
scrolling_list( => )


submit( value=nil, name=nil )
submit( VALUE, NAME => )


text_field( name="", value=nil, size=40, maxlength=nil )
text_field( NAME, VALUE, SIZE, MAXLENGTH => )


textarea( name="", cols=70, rows=10 )
textarea( NAME, COLS, ROWS => )

\

Ausserdem werden alle HTML-Tags als Methoden unterstützt. Dazu gehören auch title, head, body, br, pre usw. Der Block, der der Methode übergeben wird, muss einen String zurückgeben, der als Inhalt für den jeweiligen Tag-Typ verwendet wird. Nicht alle Tags benötigen Content: <P>, zum Beispiel, benötigt keinen. Die verfügbaren Tags variieren je nach gewähltem HTML-Level---die nachstehende Tabelle führt alle Level auf. Diesen Tag-Methoden können auch Hashes mit den Attributen für das jeweilige Tag übergeben werden. Zum Beispiel können Sie 'BORDER'=>'5' an die table-Methode übergeben, um die Linienstärke der Tabelle zu setzen.
HTML-Tags, die als Methoden zur Verfügung stehen
{HTML 3}
a address applet area b base basefont big blockquote body br caption center cite code dd dfn dir div dl dt em font form h1 h2 h3 h4 h5 h6 head hr html i img input isindex kbd li link listing map menu meta ol option p param plaintext pre samp script select small strike strong style sub sup table td textarea th title tr tt u ul var xmp
{HTML 4}
a abbr acronym address area b base bdo big blockquote body br button caption cite code col colgroup dd del dfn div dl dt em fieldset form h1 h2 h3 h4 h5 h6 head hr html i img input ins kbd label legend li link map meta noscript object ol optgroup option p param pre q samp script select small span strong style sub sup table tbody td textarea tfoot th thead title tr tt ul var
{HTML 4 Transitional}
a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dfn dir div dl dt em fieldset font form h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol optgroup option p param pre q s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var
{HTML 4 Frameset}
frame frameset

Werte in mehrteiligen Formularen

Beim Umgang mit mehrteiligen Formularen besteht das Array, das von CGI#[] zurückkommt, aus mehreren Objekten des Typs Tempfile mit den folgenden dynamisch hinzugefügten Methoden:
Methode Beschreibung
read Body
local_path Pfad zur lokalen Datei, die den Inhalt enthält
original_filename Original-Name der Datei mit dem Inhalt
content_type Content Typ

class CGI::Session
Parent: Object
Version: 1.6

Index:

new [ ] [ ]= delete update


Eine CGI::Session hält den für Web-Benutzer persistenten Status einer CGI-Umgebung. Session können im Speicher gehalten oder auf Platte abgelegt werden. Vergleiche hierzu die Diskussion unter ``Sessions'' im Kapitel ``Ruby und das Web''.

class methods
new CGI::Session.new( aCgi, [einHash]* ) -> cgi

Gibt ein neues Session-Objekt (Instanz, d.Red.) für die CGI-Anfrage zurück. Optionen, die in einHash angegeben werden können, umfassen:

Option Beschreibung
session_key Name des CGI Session-keys, um die Instanz zu identifizieren.
session_id Wert der Session-id.
new_session Wenn true wird eine neue Instanz erstellt. Wenn false, wird eine durch session_id definierte, bestehende Instanz verwendet. Wenn keine Angabe erfolgt, wird eine eventuell bestehende Instanz benutzt, sonst eine neue erstellt.
database_manager Die Klasse, die für die Speicherung der Instanzen verwendet wird; kann eine CGI::Session::FileStore- oder CGI::Session::MemoryStore- Klasse sein (oder auch eine Benutzer-definierte, wenn Sie mutig sind). Die Vorgabe ist FileStore.
tmpdir Für FileStore die Pfadangabe für Instanz-Dateien.
prefix Für FileStore das Präfix für Instanz-Dateien.

instance methods
[ ] eineSession[ einSchluessel ] -> einWert

Gibt den Wert für den angegebenen Session-key zurück.

[ ]= eineSession[ einSchluessel ] = aValue-> einWert

Setzt den Wert für den angegebenen Schlüssel.

delete eineSession.delete

Ruft die delete-Methode des zugrunde liegenden Datenbankmanagers auf. Im Falle von FileStore wird die Datei, die die Session enthält, physikalisch gelöscht. Bei MemoryStore wird die Session aus dem Speicher entfernt.

update eineSession.update

Ruft die update-Methode des zugrunde liegenden Datenbankmanagers auf. Bei FileStore werden die Sessiondaten in die Sessiondatei geschrieben. Hat mit MemoryStore keine Auswirkung.


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Übersetzung: Carsten Schinzer
Für das englische Original:
© 2000 Addison Wesley Longman, Inc. Released under the terms of the Open Publication License V1.0. That reference is available for download.
Diese Lizenz sowie das Original vom Herbst 2001 bilden die Grundlage der Übersetzung
Es wird darauf hingewiesen, dass sich die Lizenz des englischen Originals inzwischen geändert hat.
Für die deutsche Übersetzung:
© 2002 Jürgen Katins
Der Copyright-Eigner stellt folgende Lizenzen zur Verfügung:
Nicht-freie Lizenz:
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
Freie Lizenz:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".