You are reading a page on Ben Weaver's Website.

Non-blocking network I/O

2009.11.28 Read More code python io networking

I wrote a couple of toy "hello world" web servers to try using Python 3 and learn about non-blocking network programming. They are available here.

The first API I tried was kqueue it was very pleasant to work with. Since kevent() consumes a change list, only one system call is needed per event loop iteration. The API designers thoughtfully use the data attribute of EVFILT_READ events to indicate the number of bytes available to be read from a socket. This made handling incoming data very straightforward.

Next I tried pyev / libev, a generalized event loop. Its API is more complex than kqueue(), but it works across various os-specific backends (including kqueue() and epoll()). Implementing a server was straightforward, although additional logic was necessary in the read-event handler because libev does not support an equivalent to kqueue's EV_EOF flag. To determine whether a client is finished sending data without complicating the request hander, the read-event handler first receives data from the socket into a buffer. If zero bytes were received, the connection is closed.

Noteworthy parts of the Python3 library are bytearray and RawIOBase.readinto(). A bytearray is a mutable string of bytes that can be used as a buffer. The readinto() method can be used to copy data from a socket or file into a bytearray without creating an intermediate bytes object.

Code: httpd-kqueue.py, httpd-pyev.py