Non-blocking network I/O
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