De bibliotheek websockets, zonder asyncio
Wat de bibliotheek voor je deed
Je echohandler is een
Wat de bibliotheek overnam
| Op de lijn | Waar jij het schreef | Waar de bibliotheek het doet |
|---|---|---|
| De helft van de server van de | serve_handshake, check_upgrade, accept_value (hoofdstuk 2) | binnen serve, voordat je handler wordt aangeroepen |
| De helft van de client: een nieuwe sleutel, het verzoek, de controle van de acceptwaarde | make_client_key, build_upgrade_request, check_accept_response, client_handshake (hoofdstuk 2) | binnen connect, voordat het terugkeert |
| Frames: de header, de drie lengtevormen, | encode_frame, decode_frame, read_message (hoofdstuk 3 en 4) | binnen send en recv |
| Maskeren, en een frame weigeren dat voor zijn richting verkeerd gemaskeerd is | apply_mask, client_frame, en de keyword-require_mask van decode_frame (hoofdstuk 4 en 5) | binnen send en recv, per rol |
| Een | reply_to_ping (hoofdstuk 4), server_reply (hoofdstuk 5) | zodra elke ping aankomt |
| De sluithandshake | close_frame, wait_for_close (hoofdstuk 5) | binnen close, en aan het eind van het with-blok van een client |
| De verbinding laten falen met 1002, 1007 of 1009 | failure_frame (hoofdstuk 5) | zodra het foute frame aankomt, met dezelfde codes |
De laatste rij is het waard om beter te bekijken, omdat de twee het daar oneens hadden kunnen zijn. In lokale tests tegen de protocolcode van de bibliotheek werd een niet-gemaskeerd frame dat naar een bibliotheekserver werd gestuurd, beantwoord met close 1002 en de reden incorrect masking, een close-reden die geen geldige UTF-8 was met 1007, en een frame boven de groottelimiet met 1009. Dat zijn de codes die je failure_frame voor dezelfde fouten stuurt. De sluithandshake komt ook byte voor byte overeen: als de bibliotheek een close beantwoordt, stuurt ze de payload die ze ontving ongewijzigd terug, zoals je close_frame doet. Een commentaar in haar
Wat ze doet dat de jouwe niet deed
De leercodec was eerlijk over zijn grenzen, en de bibliotheek vult elk ervan in.
Fragmenten. Je codec weigerde een gefragmenteerd bericht met 1003. Een eindpunt dat aan de standaard voldoet, moet fragmenten accepteren, en de bibliotheek doet dat. In een lokale test stuurde de codec uit hoofdstuk 5 een bibliotheekserver Hel als onafgemaakt tekstfragment, daarna een ping, en daarna lo als laatste fragment. De server beantwoordde de ping met een pong, en zijn handler ontving Hello in zijn geheel en echode het.
Een client stuurt Hel en lo als twee fragmenten naar een bibliotheekserver. Wat geeft de recv van de handler terug?
Compressie. Standaard biedt de bibliotheek tijdens de handshake permessage-deflate aan, een extensie die elk bericht comprimeert (compression="deflate"). Gecomprimeerde frames zetten RSV1, een bit die je codec weigert. Dat was alleen veilig omdat je server uit hoofdstuk 5 nooit met de extensie instemde, dus de interoprun in les 1 gebruikte er geen. Deze cursus laat compressie weg.
ping_interval=20), en als de pong niet binnen 20 seconden aankomt (ping_timeout=20), sluit ze de verbinding. Je client stuurde één ping aan het begin van een gesprek, nooit een op een timer, dus een peer die zonder een woord verdween, bleef onopgemerkt totdat een leesactie een time-out kreeg. Hoofdstuk 8 gaat hierover.
Een standaard groottelimiet. De bibliotheek weigert een bericht boven 1 max_size=1048576 bytes, en sluit de verbinding met 1009. De MAX_SIZE van je codec was 1.000.000 bytes, dus de twee limieten liggen dicht bij elkaar maar zijn niet gelijk.
Deze standaardwaarden horen bij versie 17.4, degene die je vastpinde. Een andere versie kan ze veranderen, en dat is nog een reden voor de pin.
Met de standaardinstellingen stuurt een client een bericht van 2.000.000 bytes naar een bibliotheekserver. Wat gebeurt er?
Een gemak dat deze cursus overslaat
Een verbinding kan ook met een for-lus worden gelezen:
for message in connection:
connection.send(message)
De lus leest één bericht per doorgang en eindigt stil als de verbinding normaal sluit. Ze leest prettig, en ze heeft geen time-out: een client die verbinding maakt en niets zegt, houdt de lus, en haar thread, vast zolang de verbinding open blijft. Elke leesactie in deze cursus is begrensd, dus handlers lopen in een lus over recv(timeout=...) en vangen in plaats daarvan ConnectionClosed.
Waarom schrijft deze cursus niet for message in connection:?
Alles wat je nodig hebt om de echoservice uit hoofdstuk 5 opnieuw te bouwen, staat nu in echo_library.py. Het project zet het samen in een programma met een