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

impossible for your computer to reach. For example, an organization might have both an IPv4 and an<br />

IPv6 range <strong>of</strong> IP addresses; but if your particular host supports only IPv4, then you will want the results<br />

filtered to include only addresses in that family. In case the local machine has only an IPv6 network<br />

interface but the service you are connecting to is supporting only IPv4, the AI_V4MAPPED will return you<br />

those IPv4 addresses re-encoded as IPv6 addresses that you can actually use.<br />

So you will usually use getaddrinfo() this way when connecting:<br />

>>> getaddrinfo('ftp.kernel.org', 'ftp', 0, socket.SOCK_STREAM, 0,<br />

... socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)<br />

[(2, 1, 6, '', ('204.152.191.37', 21)),<br />

(2, 1, 6, '', ('149.20.20.133', 21))]<br />

And we have gotten exactly what we wanted: every way to connect to a host named ftp.kernel.org<br />

through a TCP connection to its FTP port. Note that several IP addresses were returned because this<br />

service, to spread load, is located at several different machines on the Internet. You should generally<br />

always use the first address returned, and if a connection fails, then try the remaining ones, because<br />

there is intelligence built into the name-resolution system to properly randomize the order in which you<br />

receive them. By always trying the first server IP address first, you will <strong>of</strong>fer the various servers a<br />

workload that is in the proportion that the machine administrators intend.<br />

Here is another query, which describes how I can connect from my laptop to the HTTP interface <strong>of</strong><br />

the IANA that assigns port numbers in the first place:<br />

>>> getaddrinfo('iana.org', 'www', 0, socket.SOCK_STREAM, 0,<br />

... socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)<br />

[(2, 1, 6, '', ('192.0.43.8', 80))]<br />

The IANA web site is actually a good one for demonstrating the utility <strong>of</strong> the AI_ADDRCONFIG flag,<br />

because—like any other good Internet standards organization—their web site already supports IPv6. It<br />

just so happens that my laptop can speak only IPv4 on the wireless network to which it is currently<br />

connected, so the foregoing call was careful to return only an IPv4 address. But if we take away our<br />

carefully chosen flags in the sixth parameter, then we will also be able to see their IPv6 address:<br />

>>> getaddrinfo('iana.org', 'www', 0, socket.SOCK_STREAM, 0)<br />

[(2, 1, 6, '', ('192.0.43.8', 80)),<br />

(10, 1, 6, '', ('2001:500:88:200::8', 80, 0, 0))]<br />

This can be useful if you are not going to try to use the addresses yourself, but if you are providing<br />

some sort <strong>of</strong> directory information to other hosts or programs.<br />

Asking getaddrinfo() for Pretty Hostnames<br />

One last circumstance that you will commonly encounter is where you either are making a new<br />

connection, or maybe have just received a connection to one <strong>of</strong> your own sockets, and you want an<br />

attractive hostname to display to the user or record in a log file. This is slightly dangerous because a<br />

hostname lookup can take quite a bit <strong>of</strong> time, even on the modern Internet, and might return a<br />

hostname that no longer works by the time you go and check your logs—so for log files, try to record<br />

both the hostname and raw IP address!<br />

But if you have a good use for the “canonical name” <strong>of</strong> a host, then try running getaddrinfo() with<br />

the AI_CANONNAME flag turned on, and the fourth item <strong>of</strong> any <strong>of</strong> the tuples that it returns—that were<br />

always empty strings in the foregoing examples, you will note—will contain the canonical name:<br />

>>> getaddrinfo('iana.org', 'www', 0, socket.SOCK_STREAM, 0,<br />

... socket.AI_ADDRCONFIG | socket.AI_V4MAPPED | socket.AI_CANONNAME)<br />

[(2, 1, 6, '43-8.any.icann.org', ('192.0.43.8', 80))]<br />

57

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

Saved successfully!

Ooh no, something went wrong!