Recipe 13.1. Passing Messages with Socket Datagrams
Credit: Jeff Bauer
Problem
You want to communicate small
messages between machines on a network in a lightweight fashion,
without needing absolute assurance of reliability.
Solution
This task is just what the UDP protocol is for, and Python makes it
easy for you to access UDP via datagram sockets. You can write a UDP
server script (server.py) as follows:
import socketYou can write a corresponding UDP client script
port = 8081
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Accept UDP datagrams, on the given port, from any sender
s.bind((", port))
print "waiting on port:", port
while True:
# Receive up to 1,024 bytes in a datagram
data, addr = s.recvfrom(1024)
print "Received:", data, "from", addr
(client.py) as follows:
import socket
port = 8081
host = "localhost"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto("Holy Guido! It's working.", (host, port))
Discussion
Sending short text messages with socket datagrams is simple to
implement and provides a lightweight message-passing idiom. Socket
datagrams should not be used, however, when reliable delivery of data
must be guaranteed. If the server isn't available,
your message is lost. However, in many situations, you
won't care whether the message gets lost, or, at
least, you do not want to abort a program just because a message
can't be delivered.Note that the sender of a UDP datagram (the
"client" in this example) does not
bind the socket before calling the sendto method.
On the other hand, to receive UDP datagrams, the socket does have to
be bound before calling the recvfrom method.Don't use this recipe's simple code
to send large datagram messages, especially under Windows, which may
not respect the buffer limit. To send larger messages, you may want
to do something like this:
BUFSIZE = 1024The sendto method returns the number of bytes it
while msg:
bytes_sent = s.sendto(msg[:BUFSIZE], (host, port))
msg = msg[bytes_sent:]
has actually managed to send, so each time, you retry from the point
where you left off, while ensuring that no more than
BUFSIZE octets are sent in each datagram.Note that with datagrams (UDP) you have no guarantee that all (or
any) of the pieces that you send as separate datagrams arrive to the
destination, nor that the pieces that do arrive are in the same order
in which they were sent. If you need to worry about any of these
reliability issues, you may be better off with a TCP connection,
which gives you all of these assurances and handles many delicate
behind-the-scenes aspects nicely on your behalf. Still, I often use
socket datagrams for debugging, especially (but not exclusively)
where an application spans more than one machine on the same,
reliable local area network. The Python Standard
Library's logging module also
supports optional use of UDP for its logging
output.
See Also
Recipe 13.11 for a typical,
useful application of UDP datagrams in network operations;
documentation for the standard library modules
socket and logging in the
Library Reference and Python in a
Nutshell.