09.11.2016 Views

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 5 ■ NETWORK DATA AND NETWORK ERRORS<br />

Again, most protocol designers make compression optional and simply do their own framing. But if<br />

you know ahead <strong>of</strong> time that you will always want to use zlib, then a convention like this would let you<br />

take advantage <strong>of</strong> the stream termination built into zlib and always detect the end <strong>of</strong> a compressed<br />

stream.<br />

<strong>Network</strong> Exceptions<br />

The example scripts in this book are generally designed to catch only those exceptions that are integral<br />

to the feature being demonstrated. So when we illustrated socket timeouts in Listing 2-2, we were careful<br />

to catch the exception socket.timeout since that is how timeouts are signaled; but we ignored all <strong>of</strong> the<br />

other exceptions that will occur if the hostname provided on the command line is invalid, or a remote IP<br />

is used with bind(), or the port used with bind() is already busy, or the peer cannot be contacted or<br />

stops responding.<br />

What errors can result from working with sockets? Though the number <strong>of</strong> errors that can take place<br />

while using a network connection is quite large—involving every possible misstep that can occur at<br />

every stage <strong>of</strong> the complex TCP/IP protocol, for example—the number <strong>of</strong> actual exceptions with which<br />

socket operations can hit your programs is fortunately quite few. The exceptions that are specific to<br />

socket operations are:<br />

• socket.gaierror: This exception is raised when getaddrinfo() cannot find a name<br />

or service that you ask about—hence the letters G, A, and I in its name! It can be<br />

raised not only when you make an explicit call to getaddrinfo(), but if you supply<br />

a hostname instead <strong>of</strong> an IP address to a call like bind() or connect() and the<br />

hostname lookup fails:<br />

>>> import socket<br />

>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)<br />

>>> s.connect(('nonexistent.hostname.foo.bar', 80))<br />

Traceback (most recent call last):<br />

...<br />

gaierror: [Errno -5] No address associated with hostname<br />

• socket.error: This is the workhorse <strong>of</strong> the socket module, and will be raised for<br />

nearly every failure that can happen at any stage in a network transmission.<br />

Starting with <strong>Python</strong> 2.6, this exception became, appropriately enough, a subclass<br />

<strong>of</strong> the more general IOError. This can occur during nearly any socket call, even<br />

when you least expect it—because a previous send(), for example, might have<br />

elicited a reset (RST) packet from the remote host and the error will then be<br />

delivered whenever you next try to manipulate the socket.<br />

• socket.timeout: This exception is raised only if you, or a library that you are using,<br />

decides to set a timeout on a socket rather than wait forever for a send() or recv()<br />

to complete. It indicates that the timeout was reached before the operation could<br />

complete normally.<br />

You will see that the Standard Library documentation for the socket module also describes an<br />

herror exception; fortunately, it can occur only if you use certain old-fashioned address lookup calls<br />

instead <strong>of</strong> following the practices we outlined in Chapter 4.<br />

A big question when you are using higher-level socket-based protocols from <strong>Python</strong> is whether they<br />

allow raw socket errors to hit your own code, or whether they catch them and turn them into their own<br />

kind <strong>of</strong> error.<br />

82

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

Saved successfully!

Ooh no, something went wrong!