Multicast ServerClient

 < Day Day Up > 



Multicast Server/Client

The multicast server and client are basic derivatives of the datagram code patterns. This is primarily because multicast communication is based upon the datagram model.

Multicast Server

The Python language source code for the multicast server is shown in Listing 18.5. Recall that multicast communication is group-based; therefore, a single message emitted by the server is received by every client that is currently a member of the multicast group.

After making the socket and time modules visible using the import statement (line 1), we create our address information that will be used to identify where communication will occur (lines 3 and 4). We specify our multicast IP address (noted as group) and our port number (port). Although this is a server, we don’t bind this address information to the local socket. Because we’re the multicast server, we only send datagrams and never receive. Therefore, the address information defines the group to which we’ll send datagrams (to which clients will bind).

We create our datagram socket as we’ve done in previous datagram applications in lines 7–8. We then associate the group and port variables into a single tuple called addr at line 11. This tuple will be used as the destination address later to which datagrams will be directed.

Listing 18.5 Python Daytime multicast server.

start example
  1   import socket, time  2  3   group = '239.0.0.2'  4   port = 45003  5  6   # Create a new datagram socket  7   servsock = socket.socket( socket.AF_INET,   8                             socket.SOCK_DGRAM )  9 10   # Create the destination address structure 11   addr = group, port 12 13   # The big loop 14   while 1: 15 16     # Collect the current time 17     tm = time.ctime( time.time() ) + "\n" 18 19     # Send the time to the client 20     servsock.sendto( tm, addr ) 21 22     # Wait one second before sending another time string 23     time.sleep(1)
end example

We begin our server’s infinite loop at line 14, where we’ll send out time datagrams at a rate of one per second. At line 17, we construct our time string using the time module and store the resulting string into the string variable tm. The sendto method is used at line 20 to send out the time string to the multicast group. We specify first the message to send (tm) and then the address tuple representing our multicast group (addr). We then sleep for one second at line 23 and repeat the process of emitting a new time string.

Note that nothing special was required in order to send datagrams to the multicast group. In order to receive from the multicast group, some additional setup is required. We’ll now look at these additional steps in the Multicast Client section.

Multicast Client

The Python source code for the multicast client is shown in Listing 18.6. The multicast client includes a number of new features not previously discussed, but reflects symmetry with the multicast server, as seen with prior code patterns.

In addition to importing to the socket module, we also import the string module and the struct module. We discuss the uses of these as they occur in the multicast client. We also define our group and port variables to represent our multicast address at lines 3–4. At line 7, we create a new datagram socket and make the address/port combination reusable at lines 11–12 using the SO_REUSEADDR socket option. This option is required because multiple clients may want to bind to the same multicast group/port number; otherwise, the result is one permitted bind and subsequent “address in use” errors. We then bind ourselves at line 15 to the wildcard interface and the defined port number (specified in the port variable). Although we’ve bound ourselves to our predefined multicast port number, we’re not able to receive multicast datagrams at this point. For this, we must also join the multicast group.

Let’s now look at the process of joining the multicast group. As can be seen from lines 19–23, the majority of this code is simply the construction of the mreq structure used to join the multicast group. We begin at line 19 by taking our IP address string and splitting it up into four strings (using the split method), representing each of the four numbers of a dotted-notation IP address string. The map method that is invoked over the string split converts each of the resulting strings into an integer (as defined by the int argument), storing this list in the variable bytes.

At line 21, we iterate through the bytes list and create a new 32-bit integer value of the IP address. For each byte, we perform a bitwise ‘or’ of the byte with the new variable grpAddress and then shift the entire grpAddress left eight bits. Each new iteration shifts the entire grpAddress variable eight bits to the left, and then places the new byte at the rightmost eight bits. At line 22, we create our mreq structure that consists of a 32-bit multicast address and a 32-bit interface IP address. Using the pack method from the struct module, the two 32-bit values are packed together. We specify the ‘ll’ template, which defines that those two 32-bit values will be packed into a 64-bit structure. The first 32-bit value is the group address (converted to a network address via the htonl method), and the second is the interface address (defined here as the wildcard address, INADDR_ANY). This 64-bit structure is stored within the mreq variable. As the final setup step (lines 26–27), we use the setsockopt method with the IP_ADD_MEMBERSHIP socket option to join the multicast group. We pass in the mreq variable to define the multicast group to which we want to join.

Listing 18.6 Python Daytime multicast client.

start example
 1   import socket, string, struct  2  3   group = '239.0.0.2'  4   port = 45003  5  6   # Create a new stream socket  7   sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )  8  9   # Permit multiple bindings of this address/port  10   # combination 11   sock.setsockopt( socket.SOL_SOCKET,  12                    socket.SO_REUSEADDR, 1 ) 13 14   # Bind to the INADDR_ANY and our broadcast port 15   sock.bind( ('', port) ) 16 17   # Create the mreq structure for the multicast  18   # binary group 19   bytes = map( int, string.split( group, "." ) ) 20   grpAddress = 0 21   for byte in bytes: grpAddress = (grpAddress << 8) | byte 22   mreq = struct.pack( 'll', socket.htonl(grpAddress),  23                       socket.INADDR_ANY ) 24 25   # Use the mreq structure to join the group 26   sock.setsockopt( socket.IPPROTO_IP,  27                    socket.IP_ADD_MEMBERSHIP, mreq ) 28 29   # Receive the time/date information 30   ts = sock.recv( 100 ) 31 32   # Emit the received string 33   print ts 34 35   # Leave the multicast group 36   sock.setsockopt( socket.IPPROTO_IP,  37                    socket.IP_DROP_MEMBERSHIP, mreq ) 38 39   # Close the client socket 40   sock.close()
end example

Now that we’ve joined the multicast group, we’re able to receive datagrams that have been sent to it. Using the recv method at line 30, we read a string of up to 100 bytes and store it into variable ts. This is printed at line 33 using the print statement. Once printed, we remove ourselves from the multicast group (at line 36–37) using the IP_DROP_MEMBERSHIP socket option of the setsockopt method. We then close the client socket using the close method.



 < Day Day Up > 



BSD Sockets Programming from a Multi-Language Perspective
Network Programming for Microsoft Windows , Second Edition (Microsoft Programming Series)
ISBN: 1584502681
EAN: 2147483647
Year: 2003
Pages: 225
Authors: Jim Ohlund

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net