ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2009/anyevent.pod
Revision: 1.1
Committed: Wed Jan 14 00:58:49 2009 UTC (17 years, 8 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =encoding utf-8
2    
3     =head1 AnyEvent - Eine Welt ohne Religion
4    
5     In diesem Vortrag möchte ich die neuesten Entwicklungen in Sachen
6     AnyEvent vorstellen (asynchrones IPv4/IPv6, asynchrones DNS, TLS uvm.), sowie
7     einige Hintergrundinformationen zu bestehenden Event-Modulen auf CPAN,
8     sowie Benchmarks, vorstellen.
9    
10     Doch zuerst: der Titel klingt sicherlich etwas seltsam - was bedeutet er?
11    
12     Nun, AnyEvent ist, wie im Namensteil "Event" steht, ein Event-Model
13     bzw. eine Event-Bibliothek. Event-Module oder -Bibliotheken stellen
14     im allgemeinen Funktionalität bereit, mit derer man auf Ereignisse
15     (Events), warten kann, speziell Ereignisse der Art "Zeitpunkt soundso
16     ist erreicht" und "File Descriptor soundso kann jetzt nichtblockierend
17     gelesen/geschrieben werden."
18    
19     Derartige Event-Bibliotheken gibt es zuhauf (Tk, Glib, Event, EV uvm.),
20     doch trotz der offensichtlichen Vorteile Event-basierter Programmierung
21     (z.B. beinahe automatische Parallelisierbarkeit) werden sie kaum in
22     CPAN-Modulen eingesetzt.
23    
24     Meiner Meinung nach liegt der Grund schlicht darin, daß alle diese
25     Event-Bibliotheken exklusiv sind: sie dulden niemanden neben sich. Wie
26     bei den meisten Religionen auch, muss man sich einem dieser Modelle
27     ausliefern. Konkret bedeutet dies für Modul-Autoren: benutzt man
28     z.B. Glib in seinem Modul, muss auch jeder Benutzer dieses Modules Glib
29     benutzen, was natürlich eine starke Einschränkung darstellt, vor allem,
30     wenn das Modul selbst eigentlich nur "irgendwelche" Events benötigt, die
31     im Prinzip jede beliebige Event-Bibliothek liefert.
32    
33     Einige Module auf CPAN haben versucht, aus dieser Not eine Tugend zu
34     machen: POE z.B. kann andere Event-Module als Implementation benutzen (in
35     der Praxis funktioniert das zwar nur mit einigen wenigen, aber die Idee
36     zählt). Lieder verschlimmert dies das Problem nur: POE z.B. verlangt
37     beinahe religiöse Glaubensbekenntnisse und ist kein bisschen kompatibler,
38     im Gegenteil: obwohl POE Backends für Gtk+ und Event besitzt, kann man
39     POE-Module nicht in einem Gtk+ oder Event-basiertem Programm benutzen:
40     setzt man POE in seinem Modul ein, so muss auch jeder Benutzer des Moduls
41     POE benutzen, sowie auch das Hauptprogramm selbst.
42    
43     AnyEvent dagegen ist I<grundsätzlich> anders: Im Stile von anderen
44     C<Any*>-Modulen ist es lediglich eine Schnittstelle zu diesen. Dabei passt
45     es sich an jedes unterstützte Event-Modell an, ohne daß sich die API
46     ändert. Das bedeutet, daß man getrost Module benutzen kann, die AnyEvent
47     benötigen und intern auch benutzen, aber der Benutzer des Moduls sieht
48     davon erstmal nichts und kann jede beliebige Event-Bibliothek benutzen.
49    
50     AnyEvent ist 100% Pure-Perl, und kommt mit eigener, schneller,
51     Event-Bibliothek, so daß auch auf Systemen, wo kein anderes Event-Modell
52     verfügbar ist eventbasiert Programmiert werden kann.
53    
54     =head2 AnyEvent am Beispiel AnyEvent::CouchDB
55    
56     Ein gutes Beispiel dafür ist C<AnyEvent::CouchDB>. Außer im Namen,
57     kommt AnyEvent in der API dieses Moduls nicht vor. Eine einfache
58     Datenbankabfrage sieht dementsprechend auch ganz langweilig aus:
59    
60     my $data = $db->view('users/all', { key => 'b' })->recv
61    
62     Obwohl die Abfrage selbst Ereignisgesteuert ist, muss man als Benutzer
63     des Moduls kaum darunter leiden, lediglich die Zweiteilung der Aufgabe in
64     "Start-Phase" (C<view>-Methode) und "Resultat-Phase" (C<recv>-Methode) ist
65     typisch. Daß intern AnyEvent werkelt, fällt nicht auf, außer, daß die
66     Abfrage in einem laufenden Tk/Gtk usf.-Programm dieses nicht anhält.
67    
68     Die Vorteile erscheinen, wenn man mehrere Abfragen "gleichzeitig"
69     (genauer: miteinander verflochten) ausführt:
70    
71     my @data = map $_->recv,
72     map $db->view ('users/al', { key => $_ }),
73     qw(key1 key2 key3 key4);
74    
75     Auch hierbei muss man nicht darauf achten, welches Event-Modul benutzt
76     wird (oder ob man überhaupt ein spezielles benutzt) - es funktioniert
77     einfach.
78    
79     Richtig Spaß macht es, wenn man realisiert, daß man praktisch alle
80     AnyEvent-benutzenden Module beliebig kombinieren kann, und Aufgaben
81     quasi "im Hintergrund" erledigen kann, z.B. mit C<AnyEvent::CouchDB> und
82     C<AnyEvent::HTTP>:
83    
84     $db->view('users/all', { key => 'b' })->cb (sub {
85     my $data = shift->revc;
86     # daten erhalten
87     });
88    
89     AnyEvent::HTTP::http_get "http://www.porttracker.co.uk", sub {
90     my $html = $_[1];
91     # daten erhalten
92     };
93    
94     # hier kann man weitere Dinge erledigen
95    
96     Und all das kann man in den eigenen Modulen nutzen, ohne sich irgendwie
97     auf ein bestimmtes Event-Modell festzulegen.
98    
99    
100     =head2 AnyEvent - Grundlegendes
101    
102     AnyEvent selbst wurde letztes Jahr an dieser Stelle ausführlich
103     vorgestellt, daher möchte ich hier nur eine kurze Übersicht
104     bzw. Einführung in AnyEvent als rein Event-Bibliothek geben:
105    
106     Wie viele anderen Bibliotheken auch, benutzt AnyEvent das Konzept eines
107     "Watchers", einem Objekt, daß wie ein Wachhund auf ein bestimmtes
108     Ereignis reagiert (watch/watcher = Wache/Beobachter) und bei eintreten
109     eine Aktion auslöst, z.B. aufrufen eines Callbacks.
110    
111     Diese Watcher gibt es für die folgenden Ereignistypen:
112    
113     =over 4
114    
115     =item Zeit - timer
116    
117     my $timer = AnyEvent->timer (after => 7, cb => sub {
118     warn "Sieben Sekundne sind abgelaufen!";
119     });
120    
121     Timer können nach einer gewissen Zeit ablaufen, oder wiederholt (z.B.
122     alle 3s) Ereignisse auslösen und Callbacks aufrufen.
123    
124     =item I/O auf File Handles - io
125    
126     my $watcher = AnyEvent->io (fh => *STDIN, poll => 'r', cb => sub {
127     my $line = <STDIN>;
128     # zeile von stdin gelesen
129     });
130    
131     I/O-Watcher beobachten einen File Handle und können einen Callback
132     aufrufen, wenn gelesen oder geschrieben werden kann.
133    
134     =item Signale - signal
135    
136     my $quit = AnyEvent->condvar;
137    
138     my $term = AnyEvent->signal (signal => "TERM", cb => sub {
139     $quit->send;
140     });
141    
142     ...
143    
144     $quit->recv
145    
146     Mit Signal-Watchers kann man synchron auf das Auftreten von Signalen
147     warten.
148    
149     Das obige Beispiel benutzt eine "condition variable" um mit dem
150     Hauptprogramm zu kommunizieren (mehr info s.u.).
151    
152     =item Kindprozesse sterben sehen - child
153    
154     my $w = AnyEvent->child (pid => $pid, cb => sub {
155     warn "pid $pid hat sich beendet\n";
156     });
157    
158     Eher selten benötigt, aber sehr schwer zu implementieren (wenn man es
159     richtig tun möchte :) sind Child-Watcher: mit diesen kann man auf das
160     Beenden von ge-fork-ten Prozessen warten.
161    
162     =back
163    
164     =head3 Wenn man mal nichts tun möchte
165    
166     Event-basierte APIs haben eines gemein: Im allgemeinen werden Vorgänge
167     nur gestartet und laufen dann quasi-parallel im Hintergrund ab.
168    
169     Aber wenn man nun genügend solche Vorgänge gestartet hat, möchte man ja
170     irgendwann auch mal auf die Ergebnisse warten.
171    
172     Dies erledigt entweder das Hauptprogramm, indem es die entsprechenden
173     Funktionen der Event-Bibliothek aufruft (z.B. C<Event::loop> oder C<main
174     Gtk>), oder man benutzt sogenannte "condition variables", mit denen man
175     auf das eintreten eines bestimmten Zustands warten kann.
176    
177     "Condition Variables" sind so etwas wie "Rendezvouspunkte" zwischen dem
178     Erzeuger von Daten oder einem Ereignis (z.B. C<AnyEvent::CouchDB->view>
179     oder C<AnyEvent::HTTP::http_get>, aber auch genauso C<< AnyEvent->timer
180     >>) und dem Konsumenten (der Benutzer dieser Funktionen, der die Daten
181     haben oder einfach auf das Ereignis warten möchte).
182    
183     =head1 Neues!
184    
185     Auf zu neuen Ufern - im letzten Jahr hat sich viel getan, sowohl in
186     AnyEvent selbst, als auch in Sachen "andere Module die AnyEvent benutzen".
187    
188     =head2 Altes!
189    
190     Die wichtigsten Eigenschaften von AnyEvent sind allerdings beim
191     alten geblieben:
192    
193     =over 4
194    
195     =item * Die API hat sich kaum verändert, bzw. ist 100%
196     rückwärtskompatibel.
197    
198     =item * AnyEvent ist nach wie vor "Pure-Perl".
199    
200     =item * Der Event-Teil ist nach wie vor getrennt von den anderen Teilen,
201     daß Event-Modul ist klein und wenn man bezahlt nur für daß, was man
202     benutzt.
203    
204     =back
205    
206     Aber nun zu den Neuigkeiten:
207    
208    
209     =head2 AnyEvent::Strict
210    
211     Aus Geschwindigkeitsgründen macht AnyEvent selbst keine
212     Parameterprüfung, ganz einfach deshalb, weil die Prüfung meistens mehr
213     Zeit in Anspruch nimmt als der Rest der Funktion.
214    
215     Für einen erfahrenen AnyEvent-Benutzer ist das in der Praxis kein
216     Problem, aber wenn man die API noch nicht genau kennt, können sich so
217     Fehler einschleichen (z.B. alte Event-Hasen benutzen gerne C<fd> statt
218     C<fh> um einen I/O-Watcher zu erzeugen).
219    
220     Daher bietet AnyEvent optional eine strenge Prüfung aller
221     Parameter an. Die kann man ganz einfach aktivieren, in dem man die
222     Environment-Variable C<PERL_ANYEVENT_STRICT> auf C<1> setzt, was auf allen
223     meinen Entwicklungsrechnern der Fall ist.
224    
225     Falls man diese Prüfung grundsätzlich wünscht (was ich ganz dringend
226     I<nicht> empfehle, siehe aber den Punkt "keine Religion"...), kann man diese
227     auch immer aktivieren:
228    
229     use AnyEvent;
230     use AnyEvent::Strict;
231    
232     # jetzt wird brutal geprüft.
233    
234     Ich gebe zu, daß war sicher noch nicht der Brüller, aber sehen wir
235     weiter:
236    
237     =head2 Anyevent::Util
238    
239     Dies ist meine Grabbelkiste für nützliche aber eklige Funktionen:
240    
241     =over 4
242    
243     =item fork_call BLOCK $callback
244    
245     Führt den angegebenen BLOCK in einem separaten Prozess aus und ruft
246     danach den $callback mit den Resultatwerten auf. Ist ideal, um lange
247     Berechnungen in einen separaten Prozess zu verlagern:
248    
249     fork_call {
250     find_primes_till 1e9
251     } sub {
252     warn "alle primzahen bis 10**9: ", join " ", @_;
253     };
254    
255     Die Funktion leaked allerdings unter Windows, aber ich habe bisher noch
256     keinen weg gefunden, unter einem native-win32-Perl zu forken und das Kind
257     sauber zu beenden (ich glaube, es gibt keinen)...
258    
259     =item my $guard = guard BLOCK
260    
261     Führt den angegebenen BLOCK aus, wenn C<$guard> zerstört wird. Ist
262     bei ereignisgesteuerter Programmierung total hilfreich, um Sachen
263     aufzuräumen.
264    
265     Wenn es vorhanden ist, benutzt AnyEvent das C<Guard>-Modul (ja, das ist
266     Schleichwerbung).
267    
268     =item fh_nonblocking $fh, $nonblocking
269    
270     Einen File Handle non-blocking zu machen, ist nicht ganz einfach (Windows,
271     Windows, kaputt, kaputt...). C<AnyEvent::Util> erledigt dies mit
272     furchtbaren Hacks unter Windows und elegant überall sonst.
273    
274     =back
275    
276     Immer noch nicht überzeugt? Ok, dann machen wir mal mit
277     Netzwerkprogrammierung weiter:
278    
279    
280     =head2 AnyEvent::Socket
281    
282     Sockets in Perl haben ein paar gravierende Nachteile: non-blocking
283     connects sind extrem umständlich, IPv6 und IPv4 brauchen völlig
284     inkompatible APIs, DNS blockiert den gesamtem Prozess und liefert darüber
285     hinaus auch nur altmodische IP-Adressen.
286    
287     Anders mit AnyEvent::Socket:
288    
289     tcp_connect "www.google.com", "80", sub {
290     my ($fh) = @_
291     or die "www.google.com: $!";
292    
293     ...
294     };
295    
296     Dieser Aufruf löst zuerst C<www.google.com> auf - im Hintergrund, ohne
297     das Programm anzuhalten - und baut dann, ebenfalls im Hintergrund, eine
298     TCP-Verbindung dorthin auf.
299    
300     Es versteht sich von selbst, daß Multi-Homed Hosts genauso unterstützt
301     werden wie IPv6, und das ohne zusätzliche XS-Module.
302    
303     C<tcp_connect> kann aber noch mehr. Z.b. auf Jabber-server connecten, was
304     mit Perl alleine fast unmöglich ist, da man mit Perl keine SRV-Records
305     auflösen kann:
306    
307     tcp_connect "jabber.org", "xmpp-server=5269", sub {
308     # Die pseudo-XML-Kacke parsed ihr bitte selbst...
309     }, 60; # <- timeout
310    
311     Der Name C<tcp_connect> ist leider etwas naiv, tatsächlich werden auch
312     andere Protokolle unterstützt, z.B. local unix sockets:
313    
314     tcp_connect "unix/", "/tmp/.X11-unix/X0", sub { ...
315    
316     Listening-Sockets funktionieren prinzipiell genauso einfach, z.B. hier
317     für einen TCPv6-Port:
318    
319     tcp_server "::", 80, sub {
320     my ($fh, $host, $port) = @_;
321    
322     # jede neue Verbindung führt zu einem Aufruf dieses Callbacks
323     };
324    
325     Oder einen beliebigen TCPv4-Port:
326    
327     tcp_server "0", undef, sub {
328     my ($fh, $host, $port) = @_;
329     ...
330     }, sub {
331     my ($thishost, $thisport) = @_;
332    
333     warn "bound to port $thisport\n";
334     };
335    
336     Leider muss man sich selbst darum kümmern, ob IPv6-Sockets auch auf IPv4
337     hören - üblicherweise ja, aber die BSDs haben natürlich mal wieder
338     verbockt und halten sich nicht ans RFC.
339    
340     Komplizierteres ist immer möglich - anderes als z.B. C<IO::Socket> hat
341     man volle Kontrolle über die eigentliche Socket und braucht nicht für
342     jeden etwas spezielleren Wunsch extra Support.
343    
344     Und anders als bei anderen Lösungen funktionieren diese Funktionen auch
345     unter Windows korrekt (modulo Tk, daß wie üblich zu kaputt ist, um
346     non-blocking connects stabil zu kriegen, aber AnyEvent arbeitet auch um
347     diese Bugs herum).
348    
349     Neben diesen beiden Funktionen gibt es in AnyEvent::Socket eine Unmenge an
350     Utility-Funktionen zum parsen/anzeigen von IP-Adressen, Socket-Adressen
351     und DNS:
352    
353     $ipn = parse_ipv4 $dotted_quad
354     $ipn = parse_ipv6 $textual_ipv6_address
355     $ipn = parse_address $text
356     $text = AnyEvent::Socket::aton $ipn
357     ($host, $service) = parse_hostport $string[, $default_service]
358     $sa_family = address_family $ipn
359     $text = format_address $ipn
360     $text = AnyEvent::Socket::ntoa $ipn
361     inet_aton $name_or_address, $cb->(@addresses)
362     $sa = AnyEvent::Socket::pack_sockaddr $service, $host
363     ($service, $host) = AnyEvent::Socket::unpack_sockaddr $sa
364     resolve_sockaddr $node, $service, $proto, $family, $type, $cb->([$family, $type, $proto, $sockaddr], ...)
365    
366     Hier verweise ich auf die Dokumentation. Einzig C<parse_hostport>
367     möchte ich genauer erklären: Selbst die Aufgabe, einen Hostnamen und
368     einen Port anzugeben, ist nicht ganz einfach wenn man es richtig machen
369     will. C<parse_hostport> nimmt ein oder zwei Strings und zerlegt diesen in
370     Host und Port, z.B. diese:
371    
372     www.linux.org
373     www.x.de:443
374     www.x.de:https=443
375     127.1:22
376     ::1
377     affe::1
378     [10.0.1]:80
379     [www.x.org] 17
380     10.0.0.1 smtp
381    
382     Richtig, IPv6 macht das ganze deutlich komplexer. Und IPv6 ist die
383     Zukunft, ob man das nun gut findet oder nicht :/
384    
385     Ach ja, Stichwort IPv6 - es kann auch furchtbar nervig sein, wenn
386     Programme grundsätzlich die IPv6-Adresse bevorzugen, die gerade nicht
387     erreichbar ist. Der Standard bei AnyEvent ist zur Zeit IPv4 den
388     Vorzug zu geben, was sich allerdings über die Environment-Variable
389     C<PERL_ANYEVENT_PROTOCOLS> beeinflussen lässt.
390    
391    
392     =head2 AnyEvent::DNS
393    
394     Nur am Rande möchte ich AnyEvent::DNS erwähnen. Ursprünglich war es nur
395     dazu gedacht, die Adressen für C<AnyEvent::Socket> zu resolven. Das Modul
396     ist aber ein kompletter Stub-Resolver, der beliebige DNS-Record-Typen,
397     EDNS0, IPv6 und virtual circuit mode supported.
398    
399     Das Modul ist in der Praxis ca. halb so schnell wie z.b. EV::ADNS (braucht
400     natürlich viel mehr Speicher, blockiert aber im Gegensatz zu EV::ADNS
401     nie).
402    
403     Es gibt Hilfsunktionen (hier nur eine Auswahl):
404    
405     AnyEvent::DNS::a $domain, $cb->(@addrs)
406     AnyEvent::DNS::mx $domain, $cb->(@hostnames)
407     AnyEvent::DNS::srv $service, $proto, $domain, $cb->(@srv_rr)
408     AnyEvent::DNS::ptr $domain, $cb->(@hostnames)
409     AnyEvent::DNS::reverse_lookup $ipv4_or_6, $cb->(@hostnames)
410     AnyEvent::DNS::reverse_verify $ipv4_or_6, $cb->(@hostnames)
411    
412     Und eine Resolver-Klasse:
413    
414     use Data::Dumper;
415     use AnyEvent::DNS;
416     AnyEvent::DNS::resolver->resolve (
417     "google.com", "*", my $cv = AnyEvent->condvar);
418     warn Dumper [$cv->recv];
419    
420     # gekürztes Ergebnis:
421     # [
422     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
423     # 2008052701, 7200, 1800, 1209600, 300 ],
424     # [
425     # 'google.com', 'txt', 'in',
426     # 'v=spf1 include:_netblocks.google.com ~all'
427     # ],
428     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
429     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
430     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
431     # ]
432    
433    
434     =head2 AnyEvent::Handle
435    
436     Nun zum ehrgeizigsten Teil der Neuerungen: C<AnyEvent::Handle>.
437    
438     Die Probleme, die dieses Modul lösen möchte, kommen in der Praxis
439     häufig vor: Formatted-I/O, Pipelining und TLS-Verschlüsselung.
440    
441     Früher habe ich immer ad-hoc Lösungen für diese Probleme implementiert,
442     da mir schlicht die Erfahrung gefehlt hat, wie man alle diese Features in
443     ein allgemeines Perl-Modul "gießt".
444    
445     C<AnyEvent::Handle> versucht diese Lösung zu
446     sein: AnyEvent::Handle-Objekte sind Wrapper um existierende File
447     Handles. Im folgenden beschreibe ich die Lösung, die AnyEvent::Handle
448     für die oben beschriebenen Probleme bietet:
449    
450     =over 4
451    
452     =item Formatted I/O
453    
454     Um auf ein AnyEvent::Handle-Objekt zu schreiben, benutzt man
455     C<push_write>. Das C<push> deutet darauf hin, daß es einen Puffer für
456     die Daten gibt, und C<push_write> hängt die Daten einfach an diesen an:
457    
458     $hdl->push_write ("GET / HTTP/1.0\015\012\015\012");
459    
460     Mit mehr als einem Argument fordert man zusätzliche Formatierungen an,
461     die meisten dieser Formatierungen gibt es sowohl für die Schreib- als
462     auch die Leseseite:
463    
464     $hdl->push_write (netstring => "xyz"); # djb netsrings
465     $hdl->push_write (packstring => "w", "data"); # benutzt pack()
466     $hdl->push_write (json => [1, 2, 3, 4]); # benutzt JSON
467     $hdl->push_write (storable => $ref); # benutzt Storable
468    
469     Schreiben ist einfach, Lesen ist schwieriger. Anders als beim Schreiben
470     enthält der Puffer keine Daten, sondern die Callbacks, die der Reihe nach
471     aufgerufen werden, wenn Daten eintreffen.
472    
473     Die Flexibilität entsteht dadurch, daß man Callbacks ans Ende des Puffers anhängen kann:
474    
475     $hdl->push_read (json => sub { my $data = $_[1] });
476    
477     Aber auch vor dem Anfang einschieben kann:
478    
479     $hdl->unshift_read (json => sub { my $data = $_[1] });
480    
481     Interessant ist dies vor allem, weil man hierdurch recht einfach auch
482     komplexe Protokolle mit Pipelining implementieren kann.
483    
484     Man kann jederzeit eigene Typen global für alle Handles hinzufügen, die
485     existierenden Typen sind neben denselben wie für die Schreibrichtung:
486    
487     $hdl->push_read (line => $eol, $cb); # zeilen
488     $hdl->push_Read (regex => $accept[, $reject[, $skip]); # uiuiuiui
489    
490     =item Pipelining
491    
492     Pipelining bedeutet, daß man auf einer bestehenden Verbindung mehrere
493     Anfragen gleichzeitig losschickt. Die Herausforderung liegt darin, daß
494     man beim Empfang der Antworten flexibel auf Ausnahmen reagieren können
495     muss.
496    
497     Bei HTTP beispielsweise weiß man erst nach Parsen des Headers, wie lang
498     der Body wird.
499    
500     AnyEvent::Handle erledigt dies mit einer Kombination aus C<push_read> und
501     C<unshift_read>:
502    
503     # sende requests
504     for (@urls) {
505     $hdl->push_write ("GET $_ HTTP/1.0\015\012\015\012");
506     }
507    
508     # parse antworten
509     for (@urls) {
510     # lese header
511     $hdl->push_read (line => "\015\012\015\012", sub {
512     my ($hdl, $header) = @_;
513    
514     my $content_length = extract "Content-Length", $header;
515    
516     $hdl->unshift_read (chunk => $content_length, sub {
517     my ($hdl, $body) = @_;
518    
519     # fertig
520     });
521     });
522     }
523    
524     Der springende Punkt ist, daß C<unshift_read> erst I<nach> dem Empfang
525     des Headers ausgeführt wird. Dadurch kann man z.B. verschiedene Arten von
526     Antworten parsen, oder auf unerwartete Fehler reagieren, obwohl vielleicht
527     schon Antworten auf die nächsten Requests empfangen wurden.
528    
529     =item TLS/SSL
530    
531     TLS ist der Horror. Nicht nur, aber vor allem auch wegen der grauenvollen
532     OpenSSL-API (GnuTLS ist geringfügig besser, doch sucht man vergebens nach
533     einem guten Perl-Modul dafür). Der Beweis dafür ist, daß es praktisch
534     kein Modul gibt, daß non-blocking TLS connects korrekt und wirklich
535     non-blocking durchführt.
536    
537     Es hilft auch nicht gerade, daß Net::SSLeay nur einen Bruchteil der
538     OpenSSL-API umsetzt.
539    
540     AnyEvent::Handle (to boldly go...) versucht einen ganz neuen Ansatz für
541     diese Problematik, bei der OpenSSL vom eigentlichen File Handle komplett
542     getrennt wird, d.h. gar keinen Zugriff auf diesen hat. Dadurch wird
543     garantiert, daß OpenSSL auf gar keinen Fall blockieren kann.
544    
545     =back
546    
547     Mit AnyEvent::Handle wird so manches einfach. Hier ist z.B. ein (ganz
548     primitiver) HTTPS-Client (übrigens das komplette Programm):
549    
550     use AnyEvent;
551     use AnyEvent::Socket;
552     use AnyEvent::Handle;
553    
554     my $cv = AnyEvent->condvar;
555    
556     tcp_connect "www.google.com", "443", sub {
557     my ($fh) = @_ or die;
558    
559     my $hdl; $hdl = new AnyEvent::Handle
560     fh => $fh,
561     timeout => 60,
562     tls => "connect",
563     on_eof => sub {
564     undef $hdl; # gibt handle frei
565     $cv->send; # isch hab' ferdisch
566     },
567     on_read => sub {
568     my ($hdl) = @_;
569     print $hdl->{rbuf};
570     $hdl->{rbuf} = "";
571     };
572    
573     $hdl->push_write ("GET / HTTP/1.0\015\012\015\012");
574     };
575    
576     $cv->recv;
577    
578     =back
579    
580    
581     =head2 Benchmarks
582    
583     =head2 Ausblick auf CPAN