09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 7 ■ SERVER ARCHITECTURE<br />

poll() because it produces much cleaner code, but many people choose select() because it is<br />

supported on Windows.<br />

As servers today are being asked to support greater and greater numbers <strong>of</strong> clients, some people<br />

have abandoned both select() and poll() and have opted for the epoll() mechanism provided by<br />

Linux or the kqueue() call under BSD. Some programmers have made this switch with solid numbers to<br />

back them up; other developers seem to switch simply because the latter calls are newer, but never<br />

actually check whether they will improve performance in their specific case.<br />

Which mechanism should you use in your own code?<br />

My advice is actually to avoid both <strong>of</strong> them! In my opinion, unless you have very specialized needs,<br />

you are not using your time well if you are sitting down and writing anything that looks like Listing 7–7. It<br />

is very difficult to get such code right—you will note that I myself did not include any real error handling,<br />

because otherwise the code would have become well-nigh unreadable, and the point <strong>of</strong> the listing is just<br />

to introduce the concept.<br />

Instead <strong>of</strong> sitting down with W. Richard Stevens’s Advanced <strong>Programming</strong> in the UNIX Environment<br />

and the manual pages for your operating system and trying to puzzle out exactly how to use select() or<br />

poll() with correct attention to all <strong>of</strong> the edge cases on your particular platform, you should be using an<br />

event-driven framework that does the work for you.<br />

But we will look at frameworks in a moment; first, we need to get some terminology straight.<br />

The Semantics <strong>of</strong> Non-blocking<br />

I should add a quick note about how recv() and send() behave in non-blocking mode, when you have<br />

called setblocking(False) on their socket. A poll() loop like the one just shown means that we never<br />

wind up calling either <strong>of</strong> these functions when they cannot accept or provide data. But what if we find<br />

ourselves in a situation where we want to call either function in non-blocking mode and do not yet know<br />

whether the socket is ready?<br />

For the recv() call, these are the rules:<br />

• If data is ready, it is returned.<br />

• If no data has arrived, socket.error is raised.<br />

• If the connection has closed, '' is returned.<br />

This behavior might surprise you: a closed connection returns a value, but a still-open connection<br />

raises an exception. The logic behind this behavior is that the first and last possibilities are both possible<br />

in blocking mode as well: either you get data back, or finally the connection closes and you get back an<br />

empty string. So to communicate the extra, third possibility that can happen in non-blocking mode—<br />

that the connection is still open but no data is ready yet—an exception is used.<br />

The behavior <strong>of</strong> non-blocking send() is similar:<br />

• Some data is sent, and its length is returned.<br />

• The socket buffers are full, so socket.error is raised.<br />

• If the connection is closed, socket.error is also raised.<br />

This last possibility may introduce a corner case that Listing 7–7 does not attempt to detect: that<br />

poll() could say that a socket is ready for sending, but a FIN packet from the client could arrive right<br />

after the server is released from its poll() but before it can start up its send() call.<br />

113

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!