Foundations of Python Network Programming

(WallPaper) #1
Chapter 3 ■ tCp

49

This limitation will generally not trouble you if you follow the client-server pattern shown in Listing 3-1, where
each end always reads its partner’s complete message before turning around and sending data in the other direction.
But you can run into trouble quickly if you design a client and server that leave too much data waiting without having
some arrangement for promptly reading it.
Take a look at Listing 3-2 for an example of a server and client that try to be a bit too clever without thinking
through the consequences. Here the server author has done something that is actually quite intelligent. The server’s
job is to turn an arbitrary amount of text into uppercase. Recognizing that client requests can be arbitrarily large and
that one could run out of memory trying to read an entire stream of input before trying to process it, the server reads
and processes small blocks of 1,024 bytes of data at a time.


Listing 3-2. TCP Server and Client That Can Deadlock


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter03/tcp_deadlock.py


TCP client and server that leave too much data waiting


import argparse, socket, sys


def server(host, port, bytecount):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(1)
print('Listening at', sock.getsockname())
while True:
sc, sockname = sock.accept()
print('Processing up to 1024 bytes at a time from', sockname)
n = 0
while True:
data = sc.recv(1024)
if not data:
break
output = data.decode('ascii').upper().encode('ascii')
sc.sendall(output) # send it back uppercase
n += len(data)
print('\r %d bytes processed so far' % (n,), end=' ')
sys.stdout.flush()
print()
sc.close()
print(' Socket closed')


def client(host, port, bytecount):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
bytecount = (bytecount + 15) // 16 * 16 # round up to a multiple of 16
message = b'capitalize this!' # 16-byte message to repeat over and over


print('Sending', bytecount, 'bytes of data, in chunks of 16 bytes')
sock.connect((host, port))

Free download pdf