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 7 ■ SERVER ARCHITECTURE<br />

» » client_sock, sockname = listen_sock.accept()<br />

» » handle_client(client_sock)<br />

if __name__ == '__main__':<br />

» listen_sock = launcelot.setup()<br />

» server_loop(listen_sock)<br />

Note that the server is formed <strong>of</strong> two nested loops. The outer loop, conveniently defined in a<br />

function named server_loop() (which we will use later in some other program listings), forever accepts<br />

connections from new clients and then runs handle_client() on each new socket—which is itself a loop,<br />

endlessly answering questions that arrive over the socket, until the client finally closes the connection<br />

and causes our recv_until() routine to raise EOFError.<br />

By the way, you will see that several listings in this chapter use additional ink and whitespace to<br />

include __name__ == '__main__' stanzas, despite my assertion in the preface that I would not normally do<br />

this in the published listings. The reason, as you will soon discover, is that some <strong>of</strong> the subsequent<br />

listings import these earlier ones to avoid having to repeat code. So the result, overall, will be a savings in<br />

paper!<br />

Anyway, this simple server has terrible performance characteristics.<br />

What is wrong with the simple server? The difficulty comes when many clients all want to connect at<br />

the same time. The first client’s socket will be returned by accept(), and the server will enter the<br />

handle_client() loop to start answering that first client’s questions. But while the questions and<br />

answers are trundling back and forth across the network, all <strong>of</strong> the other clients are forced to queue up<br />

on the queue <strong>of</strong> incoming connections that was created by the listen() call in the setup() routine <strong>of</strong><br />

Listing 7–1.<br />

The clients that are queued up cannot yet converse with the server; they remain idle, waiting for<br />

their connection to be accepted so that the data that they want to send can be received and processed.<br />

And because the waiting connection queue itself is only <strong>of</strong> finite length—and although we asked for<br />

a limit <strong>of</strong> 128 pending connections, some versions <strong>of</strong> Windows will actually support a queue only 5 items<br />

long—if enough incoming connections are attempted while others are already waiting, then the<br />

additional connections will either be explicitly refused or, at least, quietly ignored by the operating<br />

system. This means that the three-way TCP handshakes with these additional clients (we learned about<br />

handshakes in Chapter 3) cannot even commence until the server has finished with the first client and<br />

accepted another waiting connection from the listen queue.<br />

An Elementary Client<br />

We will tackle the deficiencies <strong>of</strong> the simple server shown in Listing 7–2 in two discussions. First, in this<br />

section, we will discuss how much time it spends waiting even on one client that needs to ask several<br />

questions; and in the next section, we will look at how it behaves when confronted with many clients at<br />

once.<br />

A simple client for the Launcelot protocol is shown in Listing 7–3. It connects, asks each <strong>of</strong> the three<br />

questions once, and then disconnects.<br />

Listing 7–3. A Simple Three-Question Client<br />

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

# <strong>Foundations</strong> <strong>of</strong> <strong>Python</strong> <strong>Network</strong> <strong>Programming</strong> - Chapter 7 - client.py<br />

# Simple Launcelot client that asks three questions then disconnects.<br />

import socket, sys, launcelot<br />

def client(hostname, port):<br />

102

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

Saved successfully!

Ooh no, something went wrong!