Guido van Rossum | 50d5e8a | 1995-03-04 22:57:56 +0000 | [diff] [blame] | 1 | # Send/receive UDP multicast packets. |
| 2 | # Requires that your OS kernel supports IP multicast. |
| 3 | # This is built-in on SGI, still optional for most other vendors. |
| 4 | # |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 5 | # Usage: |
| 6 | # mcast -s (sender) |
Guido van Rossum | c8833d4 | 1992-09-24 10:33:16 +0000 | [diff] [blame] | 7 | # mcast -b (sender, using broadcast instead multicast) |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 8 | # mcast (receivers) |
| 9 | |
| 10 | MYPORT = 8123 |
Guido van Rossum | 7814c10 | 1992-09-24 10:33:40 +0000 | [diff] [blame] | 11 | MYGROUP = '225.0.0.250' |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 12 | |
| 13 | import sys |
| 14 | import time |
| 15 | import struct |
Guido van Rossum | 7814c10 | 1992-09-24 10:33:40 +0000 | [diff] [blame] | 16 | import regsub |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 17 | from socket import * |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 18 | |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 19 | |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 20 | # Main program |
| 21 | def main(): |
| 22 | flags = sys.argv[1:] |
| 23 | # |
| 24 | if flags: |
| 25 | sender(flags[0]) |
| 26 | else: |
| 27 | receiver() |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 28 | |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 29 | |
| 30 | # Sender subroutine (only one per local area network) |
| 31 | def sender(flag): |
| 32 | s = socket(AF_INET, SOCK_DGRAM) |
| 33 | if flag == '-b': |
Guido van Rossum | c8833d4 | 1992-09-24 10:33:16 +0000 | [diff] [blame] | 34 | s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) |
| 35 | mygroup = '<broadcast>' |
| 36 | else: |
Guido van Rossum | 7814c10 | 1992-09-24 10:33:40 +0000 | [diff] [blame] | 37 | mygroup = MYGROUP |
Guido van Rossum | c8833d4 | 1992-09-24 10:33:16 +0000 | [diff] [blame] | 38 | ttl = struct.pack('b', 1) # Time-to-live |
| 39 | s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl) |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 40 | while 1: |
Guido van Rossum | c8833d4 | 1992-09-24 10:33:16 +0000 | [diff] [blame] | 41 | data = `time.time()` |
| 42 | ## data = data + (1400 - len(data)) * '\0' |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 43 | s.sendto(data, (mygroup, MYPORT)) |
Guido van Rossum | c8833d4 | 1992-09-24 10:33:16 +0000 | [diff] [blame] | 44 | time.sleep(1) |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 45 | |
Guido van Rossum | a1b51f3 | 1992-10-25 19:20:47 +0000 | [diff] [blame] | 46 | |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 47 | # Receiver subroutine (as many as you like) |
| 48 | def receiver(): |
| 49 | # Open and initialize the socket |
| 50 | s = openmcastsock(MYGROUP, MYPORT) |
| 51 | # |
Guido van Rossum | 4fab6a5 | 1992-09-08 21:19:55 +0000 | [diff] [blame] | 52 | # Loop, printing any data we receive |
| 53 | while 1: |
| 54 | data, sender = s.recvfrom(1500) |
| 55 | while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's |
| 56 | print sender, ':', `data` |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 57 | |
| 58 | |
| 59 | # Open a UDP socket, bind it to a port and select a multicast group |
| 60 | def openmcastsock(group, port): |
| 61 | # Import modules used only here |
Guido van Rossum | 4f1a618 | 1999-08-07 14:01:05 +0000 | [diff] [blame^] | 62 | import string |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 63 | import struct |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 64 | # |
| 65 | # Create a socket |
Guido van Rossum | 50d5e8a | 1995-03-04 22:57:56 +0000 | [diff] [blame] | 66 | s = socket(AF_INET, SOCK_DGRAM) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 67 | # |
| 68 | # Allow multiple copies of this program on one machine |
| 69 | # (not strictly needed) |
Guido van Rossum | 48b805c | 1998-01-15 22:36:13 +0000 | [diff] [blame] | 70 | s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 71 | # |
| 72 | # Bind it to the port |
Guido van Rossum | 00d5974 | 1994-10-08 19:13:48 +0000 | [diff] [blame] | 73 | s.bind(('', port)) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 74 | # |
| 75 | # Look up multicast group address in name server |
| 76 | # (doesn't hurt if it is already in ddd.ddd.ddd.ddd format) |
Guido van Rossum | 50d5e8a | 1995-03-04 22:57:56 +0000 | [diff] [blame] | 77 | group = gethostbyname(group) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 78 | # |
| 79 | # Construct binary group address |
Guido van Rossum | 4f1a618 | 1999-08-07 14:01:05 +0000 | [diff] [blame^] | 80 | bytes = map(int, string.split(group, ".")) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 81 | grpaddr = 0 |
| 82 | for byte in bytes: grpaddr = (grpaddr << 8) | byte |
| 83 | # |
| 84 | # Construct struct mreq from grpaddr and ifaddr |
| 85 | ifaddr = INADDR_ANY |
Guido van Rossum | 4f1a618 | 1999-08-07 14:01:05 +0000 | [diff] [blame^] | 86 | mreq = struct.pack('ll', htonl(grpaddr), htonl(ifaddr)) |
Guido van Rossum | bd07b31 | 1992-11-16 16:54:45 +0000 | [diff] [blame] | 87 | # |
| 88 | # Add group membership |
| 89 | s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq) |
| 90 | # |
| 91 | return s |
| 92 | |
| 93 | |
| 94 | main() |