I l@ve RuBoard Previous Section Next Section

10.4 Passing Messages with Socket Datagrams

Credit: Jeff Bauer

10.4.1 Problem

You need to communicate small messages between machines on a TCP/IP network in a lightweight fashion, without needing absolute assurance of reliability.

10.4.2 Solution

This is what the UDP protocol is for, and Python makes it easy for you to access it, via datagram sockets. You can write a server (server.py) as follows:

import socket
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 1:
    # Receive up to 1,024 bytes in a datagram
    data, addr = s.recvfrom(1024)
    print "Received:", data, "from", addr

And you can write a client (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))

10.4.3 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, there are many situations in which you won't care whether the message gets lost, or, at least, you won't want to abort a program just because the message can't be delivered.

Note that the sender of a UDP datagram (the client in this example) does not need to bind the socket before calling the sendto method. On the other hand, to receive UDP datagrams, the socket does need to be bound before calling the recvfrom method.

Don't use this recipe's simple code to send very large datagram messages, especially under Windows, which may not respect the buffer limit. To send larger messages, you will probably want to do something like this:

BUFSIZE = 1024
while msg:
    bytes_sent = s.sendto(msg[:BUFSIZE], (host, port))
    msg = msg[bytes_sent:]

The sendto method returns the number of bytes it 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 none 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 that 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 the application spans more than one machine on the same, reliable local area network.

10.4.4 See Also

Recipe 10.13 for a typical, useful application of UDP datagrams in network operations; documentation for the standard library module socket in the Library Reference.

    I l@ve RuBoard Previous Section Next Section