Chapter 2 ■ UDp
20
The underlying system calls for networking, on both Windows and POSIX systems (like Linux and Mac OS X),
center around the idea of a communications endpoint called a socket. The operating system uses integers to identify
sockets, but Python instead returns a more convenient socket.socket object to your Python code. It remembers the
integer internally (you can call its fileno() method to peek at it) and uses it automatically every time you call one of
its methods to request that a system call be run on the socket.
■ Note On pOSIX systems, the fileno() integer that identifies a socket is also a file descriptor drawn from the pool of
integers representing open files. You might run across code that, assuming a pOSIX environment, fetches this
integer and then uses it to perform non-networking calls like os.read() and os.write() on the file descriptor to do
filelike things with what is actually a network communications endpoint. however, because the code in this book is
designed to work on Windows as well, you will perform only true socket operations on your sockets.
What do sockets look like in operation? Take a look at Listing 2-1, which shows a simple UDP server and client.
You can see already that it makes only one Python Standard Library call, to the function socket.socket(), and that all
of the other calls are to the methods of the socket object it returns.
Listing 2-1. UDP Server and Client on the Loopback Interface
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter02/udp_local.py
UDP client and server on localhost
import argparse, socket
from datetime import datetime
MAX_BYTES = 65535
def server(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', port))
print('Listening at {}'.format(sock.getsockname()))
while True:
data, address = sock.recvfrom(MAX_BYTES)
text = data.decode('ascii')
print('The client at {} says {!r}'.format(address, text))
text = 'Your data was {} bytes long'.format(len(data))
data = text.encode('ascii')
sock.sendto(data, address)
def client(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
text = 'The time is {}'.format(datetime.now())
data = text.encode('ascii')
sock.sendto(data, ('127.0.0.1', port))
print('The OS assigned me the address {}'.format(sock.getsockname()))
data, address = sock.recvfrom(MAX_BYTES) # Danger!
text = data.decode('ascii')
print('The server {} replied {!r}'.format(address, text))