Chapter 3 ■ tCp
42
Note that while a passive socket is made unique by the interface address and port number at which it is
listening—no one else is allowed to grab that same address and port—there can be many active sockets that all share
the same local socket name. A busy web server to which a thousand clients have all made HTTP connections, for
example, will have a thousand active sockets all bound to its public IP address at TCP port 80. What makes an active
socket unique is, rather, the four-part coordinate, shown here:
(local_ip, local_port, remote_ip, remote_port)
It is this four-tuple by which the operating system names each active TCP connection, and incoming TCP packets
are examined to see whether their source and destination address associate them with any of the currently active
sockets on the system.
A Simple TCP Client and Server
Take a look at Listing 3-1. As I did in the previous chapter, I have here combined what could have been two separate
programs into a single listing—both because they share a bit of common code and so that the client and server code
can be read together more easily.
Listing 3-1. Simple TCP Server and Client
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter03/tcp_sixteen.py
Simple TCP client and server that send and receive 16 octets
import argparse, socket
def recvall(sock, length):
data = b''
while len(data) < length:
more = sock.recv(length - len(data))
if not more:
raise EOFError('was expecting %d bytes but only received'
' %d bytes before the socket closed'
% (length, len(data)))
data += more
return data
def server(interface, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((interface, port))
sock.listen(1)
print('Listening at', sock.getsockname())
while True:
sc, sockname = sock.accept()
print('We have accepted a connection from', sockname)
print(' Socket name:', sc.getsockname())
print(' Socket peer:', sc.getpeername())
message = recvall(sc, 16)
print(' Incoming sixteen-octet message:', repr(message))
sc.sendall(b'Farewell, client')
sc.close()
print(' Reply sent, socket closed')