[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

However used, select lets us direct attention to sockets ready to communicate, so as
to avoid blocking on calls to ones that are not. That is, when the sources passed to
select are sockets, we can be sure that socket calls like accept, recv, and send will not
block (pause) the server when applied to objects returned by select. Because of that,
a single-loop server that uses select need not get stuck communicating with one client
or waiting for new ones while other clients are starved for the server’s attention.


Because this type of server does not need to start threads or processes, it can be efficient
when transactions with clients are relatively short-lived. However, it also requires that
these transactions be quick; if they are not, it still runs the risk of becoming bogged
down waiting for a dialog with a particular client to end, unless augmented with threads
or forks for long-running transactions.‖


A select-based echo server


Let’s see how all of this translates into code. The script in Example 12-9 implements
another echo server, one that can handle multiple clients without ever starting new
processes or threads.


Example 12-9. PP4E\Internet\Sockets\select-server.py


"""
Server: handle multiple clients in parallel with select. use the select
module to manually multiplex among a set of sockets: main sockets which
accept new client connections, and input sockets connected to accepted
clients; select can take an optional 4th arg--0 to poll, n.m to wait n.m
seconds, or omitted to wait till any socket is ready for processing.
"""


import sys, time
from select import select
from socket import socket, AF_INET, SOCK_STREAM
def now(): return time.ctime(time.time())


myHost = '' # server machine, '' means local host
myPort = 50007 # listen on a non-reserved port number
if len(sys.argv) == 3: # allow host/port as cmdline args too
myHost, myPort = sys.argv[1:]
numPortSocks = 2 # number of ports for client connects


make main sockets for accepting new client requests


mainsocks, readsocks, writesocks = [], [], []
for i in range(numPortSocks):
portsock = socket(AF_INET, SOCK_STREAM) # make a TCP/IP socket object


‖Confusingly, select-based servers are often called asynchronous, to describe their multiplexing of short-lived
transactions. Really, though, the classic forking and threading servers we met earlier are asynchronous, too,
as they do not wait for completion of a given client’s request. There is a clearer distinction between serial and
parallel servers—the former process one transaction at a time and the latter do not—and “synchronous” and
“asynchronous” are essentially synonyms for “serial” and “parallel.” By this definition, forking, threading,
and select loops are three alternative ways to implement parallel, asynchronous servers.


Handling Multiple Clients | 821
Free download pdf