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 3 ■ TCP<br />

As before, my operating system uses the special IP address 0.0.0.0 to mean “accept connections on<br />

any interface,” but that may vary with operating system, and <strong>Python</strong> hides this fact by letting you use the<br />

empty string instead.<br />

Deadlock<br />

The term “deadlock” is used for all sorts <strong>of</strong> situations in computer science where two programs, sharing<br />

limited resources, can wind up waiting on each other forever because <strong>of</strong> poor planning. It turns out that<br />

it can happen fairly easily when using TCP.<br />

I mentioned previously that typical TCP stacks use buffers, both so that they have somewhere to<br />

place incoming packet data until an application is ready to read it, and so that they can collect outgoing<br />

data until the network hardware is ready to transmit an outgoing packet. These buffers are typically<br />

quite limited in size, and the system is not generally willing to let programs fill all <strong>of</strong> RAM with unsent<br />

network data. After all, if the remote end is not yet ready to process the data, it makes little sense to<br />

expend system resources on the generating end trying to produce more <strong>of</strong> it.<br />

This limitation will generally not trouble you if you follow the client-server pattern shown in Listing<br />

3–1, where each end always reads its partner’s complete message before turning around and sending<br />

data in the other direction. But you can run into trouble very quickly if you design a client and server<br />

that leave too much data waiting without having some arrangement for promptly reading it.<br />

Take a look at Listing 3–2 for an example <strong>of</strong> a server and client that try to be a bit too clever without<br />

thinking through the consequences. Here, the server author has done something that is actually quite<br />

intelligent. His job is to turn an arbitrary amount <strong>of</strong> text into uppercase. Recognizing that its client’s<br />

requests can be arbitrarily large, and that one could run out <strong>of</strong> memory trying to read an entire stream <strong>of</strong><br />

input before trying to process it, the server reads and processes small blocks <strong>of</strong> 1,024 bytes at a time.<br />

Listing 3–2. TCP Server and Client That Deadlock<br />

#!/usr/bin/env python<br />

# <strong>Foundations</strong> <strong>of</strong> <strong>Python</strong> <strong>Network</strong> <strong>Programming</strong> - Chapter 3 - tcp_deadlock.py<br />

# TCP client and server that leave too much data waiting<br />

import socket, sys<br />

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

HOST = '127.0.0.1'<br />

PORT = 1060<br />

if sys.argv[1:] == ['server']:<br />

» s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)<br />

» s.bind((HOST, PORT))<br />

» s.listen(1)<br />

» while True:<br />

» » print 'Listening at', s.getsockname()<br />

» » sc, sockname = s.accept()<br />

» » print 'Processing up to 1024 bytes at a time from', sockname<br />

» » n = 0<br />

» » while True:<br />

» » » message = sc.recv(1024)<br />

» » » if not message:<br />

» » » » break<br />

» » » sc.sendall(message.upper()) # send it back uppercase<br />

» » » n += len(message)<br />

44

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

Saved successfully!

Ooh no, something went wrong!