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
that 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