Die Bibliothek websockets, ohne asyncio
Was die Bibliothek für dich getan hat
Dein Echo-Handler ist eine
Was die Bibliothek übernommen hat
| Auf der Leitung | Wo du es geschrieben hast | Wo die Bibliothek es erledigt |
|---|---|---|
| Die Hälfte des Servers beim | serve_handshake, check_upgrade, accept_value (Kapitel 2) | in serve, bevor dein Handler aufgerufen wird |
| Die Hälfte des Clients: ein neuer Schlüssel, die Anfrage, die Prüfung des Accept-Werts | make_client_key, build_upgrade_request, check_accept_response, client_handshake (Kapitel 2) | in connect, bevor es zurückkehrt |
| Frames: der Header, die drei Längenformen, | encode_frame, decode_frame, read_message (Kapitel 3 und 4) | in send und recv |
| Maskieren und das Ablehnen eines Frames, der für seine Richtung falsch maskiert ist | apply_mask, client_frame und der Schlüsselwortparameter require_mask von decode_frame (Kapitel 4 und 5) | in send und recv, je nach Rolle |
| Einen | reply_to_ping (Kapitel 4), server_reply (Kapitel 5) | sobald jeder Ping ankommt |
| Der Schließ-Handshake | close_frame, wait_for_close (Kapitel 5) | in close und am Ende des with-Blocks eines Clients |
| Die Verbindung mit 1002, 1007 oder 1009 scheitern lassen | failure_frame (Kapitel 5) | sobald der fehlerhafte Frame ankommt, mit denselben Codes |
Die letzte Zeile verdient einen genaueren Blick, weil die beiden hier hätten voneinander abweichen können. In lokalen Tests gegen den Protokollcode der Bibliothek wurde ein unmaskierter Frame an einen Bibliotheks-Server mit Close 1002 und dem Grund incorrect masking beantwortet, ein Close-Grund, der kein gültiges UTF-8 war, mit 1007 und ein Frame über der Größengrenze mit 1009. Das sind die Codes, die dein failure_frame für dieselben Fehler sendet. Auch der Schließ-Handshake stimmt Byte für Byte überein: Wenn die Bibliothek einen Close beantwortet, sendet sie die Payload, die sie empfangen hat, unverändert zurück, wie es dein close_frame tut. Ein Kommentar in ihrem Quelltext erklärt, warum: Einen leeren Close neu aufzubauen würde scheitern, weil ein leerer Close als 1005 gemeldet wird, ein Code, der nicht gesendet werden darf.
Was sie tut, das deiner nicht getan hat
Der Lern-Codec war ehrlich, was seine Grenzen angeht, und die Bibliothek füllt jede davon aus.
Fragmente. Dein Codec hat eine fragmentierte Nachricht mit 1003 abgelehnt. Ein konformer Endpunkt muss Fragmente akzeptieren, und die Bibliothek tut das. In einem lokalen Test hat der Codec aus Kapitel 5 einem Bibliotheks-Server Hel als unfertiges Text-Fragment gesendet, dann einen Ping, dann lo als letztes Fragment. Der Server hat den Ping mit einem Pong beantwortet, und sein Handler hat Hello am Stück empfangen und als Echo zurückgesendet.
Ein Client sendet Hel und lo als zwei Fragmente an einen Bibliotheks-Server. Was gibt das recv des Handlers zurück?
Kompression. Standardmäßig bietet die Bibliothek während des Handshakes permessage-deflate an, eine Erweiterung, die jede Nachricht komprimiert (compression="deflate"). Komprimierte Frames setzen RSV1, ein Bit, das dein Codec ablehnt. Das war nur sicher, weil dein Server aus Kapitel 5 der Erweiterung nie zugestimmt hat, also hat der Interop-Lauf in Lektion 1 keine verwendet. Dieser Kurs lässt Kompression weg.
ping_interval=20), und wenn der Pong nicht innerhalb von 20 Sekunden ankommt (ping_timeout=20), schließt sie die Verbindung. Dein Client hat zu Beginn eines Gesprächs einen Ping gesendet, nie einen nach Zeitplan, also blieb eine Gegenseite, die kommentarlos verschwunden ist, unbemerkt, bis ein Lesevorgang in ein Timeout lief. Darum geht es in Kapitel 8.
Eine Standard-Größengrenze. Die Bibliothek lehnt eine Nachricht über 1 max_size=1048576 Bytes, und schließt die Verbindung mit 1009. Das MAX_SIZE deines Codecs war 1.000.000 Bytes, also liegen die beiden Grenzen nahe beieinander, sind aber nicht gleich.
Diese Standardwerte gehören zu Version 17.4, der, die du festgelegt hast. Eine andere Version kann sie ändern, und das ist ein weiterer Grund für die Festlegung.
Mit Standardeinstellungen sendet ein Client eine Nachricht von 2.000.000 Bytes an einen Bibliotheks-Server. Was passiert?
Eine Bequemlichkeit, die dieser Kurs auslässt
Eine Verbindung kann auch mit einer for-Schleife gelesen werden:
for message in connection:
connection.send(message)
Die Schleife liest eine Nachricht pro Durchlauf und endet still, wenn die Verbindung normal schließt. Sie liest sich gut, und sie hat kein Timeout: Ein Client, der sich verbindet und nichts sagt, hält die Schleife und ihren Thread fest, so lange die Verbindung offen bleibt. Jeder Lesevorgang in diesem Kurs ist begrenzt, also durchlaufen Handler stattdessen recv(timeout=...) in einer Schleife und fangen ConnectionClosed ab.
Warum schreibt dieser Kurs nicht for message in connection:?
Alles, was du brauchst, um den Echo-Dienst aus Kapitel 5 neu zu bauen, steht jetzt in echo_library.py. Das Projekt fügt es zu einem Programm mit einer