Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Matthews Lab
Search
Search
Appearance
Log in
Personal tools
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
P2pd
(section)
Page
Discussion
British English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
= Python async networking = I started my async journey by looking through the examples in the online Python docs. These docs are great and remind me of the developer-friendly PHP docs. Eventually I found an example for a TCP server. <syntaxhighlight lang="python">class ProtocolClass(asyncio.Protocol): # ... callback methods here # e.g. data_receive(self, data) ... # (There is a different function to call for UDP servers that does the same thing.) server = await loop.create_server( # Factory for making Protocol objects for new clients. lambda: ProtocolClass(), # Details for the listen socket ... '127.0.0.1', 8888 )</syntaxhighlight> '''What this code means is:''' every time a new client connects – create a Protocol object for them. The method that does this is the ‘factory’ lambda function. The class also has special callback methods that are run for various events. It’s pretty simple. Unfortunately, the moment you try use async functions you’re in for a world of pain. As I learned: Python does indeed have async networking features. It turns out you can use '''loop.create_connection'''. So if you want to write ‘await connection() … await send … await recv’ for TCP – this code is for you. <syntaxhighlight lang="python"># Open a new TCP connection. reader, writer = await asyncio.open_connection('127.0.0.1', 8888) # Send some data down the socket. writer.write(b"message") await writer.drain() # Read some data back. data = await reader.read(100) # Close the socket. writer.close() await writer.wait_closed() # You may be wondering what the 'async' version for UDP looks like? # ... and the answer is: there isn't one.</syntaxhighlight> The main benefit to using async await is the program preserves its sequential control flow but ‘blocking’ operations don’t stop the program. Instead, if a task needs to wait for a result, execution is given back to the event loop, and other tasks are free to run or be resumed when they’re ready. One disadvantage to coroutines is you have to manually check for changes. E.g. if there’s new data to be read from a stream it’s your job to await it. '''From these examples – a myriad of issues stands out to me:''' # Protocol classes and async functions force you to choose between them. Neither is compatible with the other. # The APIs for TCP and UDP are different. For Protocol classes even the method names vary. # There is no async equivalent of ‘reader-writer streams’ for UDP. # The way server listen sockets bind to interfaces is poorly defined (if at all.) # IPv6 is painful to use in Python and requires specialised code to handle all address types. # Having to manage two objects for TCP (a reader and writer stream) is … annoying. My idea to solve these problems is to encapsulate everything in a well-designed, consistent API. The API should allow endpoints to be used with both async functions and Protocol-style callbacks; It should not have any transport-specific code (so the same code will work with TCP and UDP); It should support network interfaces well; And IPv6 should be as easy to use as IPv4. Here’s what I came up with. <span id="p2pd-async-networking-library"></span>
Summary:
Please note that all contributions to Matthews Lab may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Matthews Lab:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)