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 4 ■ SOCKET NAMES AND DNS<br />

<strong>Python</strong> code to make extra calls if the user might want to provide a symbolic port number like www or<br />

smtp instead <strong>of</strong> 80 or 25.<br />

Asking getaddrinfo() Where to Bind<br />

Before tackling all <strong>of</strong> the options that getaddrinfo() supports, it will be more useful to see how it is used<br />

to support three basic network operations. We will tackle them in the order that you might perform<br />

operations on a socket: binding, connecting, and then identifying a remote host who has sent you<br />

information.<br />

If you want an address to provide to bind(), either because you are creating a server socket or<br />

because you for some reason want your client to be connecting to someone else but from a predictable<br />

address, then you will call getaddrinfo() with None as the hostname but with the port number and<br />

socket type filled in. Note that here, as in the following getaddrinfo() calls, zeros serve as wildcards in<br />

fields that are supposed to contain numbers:<br />

>>> from socket import getaddrinfo<br />

>>> getaddrinfo(None, 'smtp', 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)<br />

[(2, 1, 6, '', ('0.0.0.0', 25)), (10, 1, 6, '', ('::', 25, 0, 0))]<br />

>>> getaddrinfo(None, 53, 0, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)<br />

[(2, 2, 17, '', ('0.0.0.0', 53)), (10, 2, 17, '', ('::', 53, 0, 0))]<br />

Here we asked about where we should bind() a socket if we want to serve SMTP traffic using TCP,<br />

and if we want to serve DNS traffic using DCP, respectively. The answers we got back in each case are the<br />

appropriate wildcard addresses that will let us bind to every IPv4 and every IPv6 interface on the local<br />

machine with all <strong>of</strong> the right values for the socket family, socket type, and protocol in each case.<br />

If you instead want to bind() to a particular IP address that you know that the local machine holds,<br />

then omit the AI_PASSIVE flag and just specify the hostname. For example, here are two ways that you<br />

might try binding to localhost:<br />

>>> getaddrinfo('127.0.0.1', 'smtp', 0, socket.SOCK_STREAM, 0)<br />

[(2, 1, 6, '', ('127.0.0.1', 25))]<br />

>>> getaddrinfo('localhost', 'smtp', 0, socket.SOCK_STREAM, 0)<br />

[(10, 1, 6, '', ('::1', 25, 0, 0)), (2, 1, 6, '', ('127.0.0.1', 25))]<br />

You can see that supplying the IPv4 address for the localhost locks you down to receiving<br />

connections only over IPv4, while using the symbolic name localhost (at least on my Linux laptop, with<br />

a well-configured /etc/hosts file) makes available both the IPv4 and IPv6 local names for the machine.<br />

One question that you might already be asking at this point, by the way, is what on earth you are<br />

supposed to do when you assert that you want to supply a basic service and getaddrinfo() goes and<br />

gives you several addresses to use—you certainly cannot create a single socket and bind() it to more<br />

than one address! In Chapter 7, we will tackle the techniques that you can use if you are writing server<br />

code and want to have several sockets going at once.<br />

Asking getaddrinfo() About Services<br />

Except for the use shown in the previous section, all other uses <strong>of</strong> getaddrinfo() are outward-looking,<br />

and generate information suitable for connecting you to other applications. In all such cases, you can<br />

either use an empty string to indicate that you want to connect back to the localhost using the loopback<br />

interface, or provide a string giving an IPv4 address, IPv6 address, or hostname to name your<br />

destination.<br />

The usual use <strong>of</strong> getaddrinfo() in all other cases—which, basically, is when you are preparing to<br />

connect() or sendto()—is to specify the AI_ADDRCONFIG flag, which filters out any addresses that are<br />

56

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

Saved successfully!

Ooh no, something went wrong!