0%

De bibliotheek websockets, zonder asyncio

Wat de bibliotheek voor je deed

Je echohandler is een van een paar regels, en je client een paar meer. Hoofdstuk 2 tot en met 5 hadden 618 regels nodig, verdeeld over drie bestanden, om hetzelfde werk te doen. Niets van dat werk is verdwenen: elk krijgt nog steeds een header, elk clientframe wordt nog steeds gemaskeerd, elke close wordt nog steeds beantwoord. De bibliotheek doet het nu. Deze les legt de twee naast elkaar, zodat elk ding dat de bibliotheek doet een naam heeft die je kent, en bekijkt daarna wat de bibliotheek doet dat je code nooit deed.

Wat de bibliotheek overnam

Op de lijnWaar jij het schreefWaar de bibliotheek het doet
De helft van de server van de : het verzoek lezen, controleren, 101 antwoorden met de acceptwaardeserve_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 acceptwaardemake_client_key, build_upgrade_request, check_accept_response, client_handshake (hoofdstuk 2)binnen connect, voordat het terugkeert
Frames: de header, de drie lengtevormen, voor tekstencode_frame, decode_frame, read_message (hoofdstuk 3 en 4)binnen send en recv
Maskeren, en een frame weigeren dat voor zijn richting verkeerd gemaskeerd isapply_mask, client_frame, en de keyword- require_mask van decode_frame (hoofdstuk 4 en 5)binnen send en recv, per rol
Een beantwoorden met een pong met dezelfde payloadreply_to_ping (hoofdstuk 4), server_reply (hoofdstuk 5)zodra elke ping aankomt
De sluithandshakeclose_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 1009failure_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 legt uit waarom: een lege close opnieuw opbouwen zou falen, omdat een lege close wordt gemeld als 1005, een code die niet verstuurd mag worden.

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.

. Elke 20 seconden stuurt de bibliotheek een ping (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 .