Chapter 3 ■ tCp
50
sent = 0
while sent < bytecount:
sock.sendall(message)
sent += len(message)
print('\r %d bytes sent' % (sent,), end=' ')
sys.stdout.flush()
print()
sock.shutdown(socket.SHUT_WR)
print('Receiving all the data the server sends back')
received = 0
while True:
data = sock.recv(42)
if not received:
print(' The first data received says', repr(data))
if not data:
break
received += len(data)
print('\r %d bytes received' % (received,), end=' ')
print()
sock.close()
if name == 'main':
choices = {'client': client, 'server': server}
parser = argparse.ArgumentParser(description='Get deadlocked over TCP')
parser.add_argument('role', choices=choices, help='which role to play')
parser.add_argument('host', help='interface the server listens at;'
' host the client sends to')
parser.add_argument('bytecount', type=int, nargs='?', default=16,
help='number of bytes for client to send (default 16)')
parser.add_argument('-p', metavar='PORT', type=int, default=1060,
help='TCP port (default 1060)')
args = parser.parse_args()
function = choices[args.role]
function(args.host, args.p, args.bytecount)
It can split the work up so easily—without needing to do framing or analysis—because it is merely trying to run
the upper() string method on plain ASCII characters. This is an operation that can be performed separately on each
block of input, without worrying about the blocks that came before or after. Things would not be this simple for the
server if it were trying to run a more sophisticated string operation like title(), which would capitalize a letter in the
middle of a word if the word happened to be split across a block boundary without being properly reassembled. For
example, if a particular data stream got split into 16-byte blocks, then errors would creep in like this:
message = 'the tragedy of macbeth'
blocks = message[:16], message[16:]
''.join( b.upper() for b in blocks ) # works fine
'THE TRAGEDY OF MACBETH'
''.join( b.title() for b in blocks ) # whoops
'The Tragedy Of MAcbeth'