An Asyncio socket tutorial

How to build an ASGI web server, like Hypercorn

Philip Jones
Aug 20, 2018 · 4 min read

There are many asyncio tutorials and articles that focus on coroutines, the event loop, and simple primitives. There are fewer that focus on using sockets, for either listening for or sending to connections. This article will show how to build a simple web server.

This is based on the development of Hypercorn, which is an ASGI server that supports HTTP/1, HTTP/2, and Websockets. The Hypercorn code is the follow on for this article.

Echo Server

An echo server is the simplest place to start, and by definition simply echos back to the client any data sent. As we are aiming to build a web server the TCP (Protocol) makes sense.

Asyncio has two high level choices for writing servers, either callback based or stream based. I think the latter is conceptually clearer, but has been shown to have worse performance. So we’ll do both, starting with stream based, (also note I’ll be using Python3.7 features, such as the serve_forever),

If you run this code and then connect via telnet localhost 5000 or equivalent you should see the server echo back everything sent. The equivalent code using callbacks, termed a Protocol is,

HTTP Server

Now we are able to open a socket listen for connections and respond, we can add HTTP as the communication protocol and then have a webserver. To start with lets simply echo back the important parts of a HTTP message, i.e. the verb, request target, and any headers.

At this stage we need to read RFC 7230 and write a HTTP parser, or use one that already exists. The latter is much easier, and h11 is fantastic so we’ll use that instead.

h11 is a sans-io library, this means that it manages a HTTP connection without managing the IO. In practice this means that any bytes received have to be passed to the h11 connection and any bytes to be sent have to be retrieved from the h11 connection which allows the h11 connection object to manage the HTTP state.

As an example a simple request response sequence is given below, note how the received bytes must be provided to h11 and how the response data is provided by h11,

We’ll stick with the Protocol server, on the basis of performance, and add h11,

If you run this code and make a HTTP request, e.g. curl localhost:5000/path you will receive GET /path back.

Timeouts & Flow Control

Whilst the above gives a basic HTTP server, we should add flow control and timeouts to ensure it isn’t trivially attacked. These attacks typically attempt to exhaust the server’s resources (sockets, memory, cpu…) so that it can no longer serve new connections.

To start lets consider a malicious client that opens many connections to the server, and holds them open without doing anything. This exhausts the connections the server has, thereby preventing anyone else from connecting.

To combat this the server should timeout an idle connection, that is wait a certain length of time for the client to do something and then close the connection if it doesn’t. Using a protocol server this can be done as follows,

In the initial echo server example we had await writer.drain() as this paused the coroutine from writing more data to the socket till the client had caught up, it drained the socket. This is useful as until the client catches up the data will be stored in memory, hence a malicious client can make many requests for a lot of data, refuse to receive the data, and allow the server to exhaust its memory.

To combat this the coroutine sending data should await a drain function, that can be added to the protocol,


This is really all there is with respect to asyncio to build an ASGI server. To continue you’ll need to add pipelining, ASGI constructs, the request-body, and streaming as completed in the Hypercorn file. See also the h2, and wsproto libraries for the HTTP/2 and Websocket equivalents of h11.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store