Multicast ServerClient

 < Day Day Up > 



Multicast Server/Client

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

Multicast Server

The Ruby language source code for the multicast server is shown in Listing 20.6. 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.

As multicast communication has been discussed in previous chapters, we’ll forgo discussion of multicast specifics and concentrate solely on the methods that Ruby provides to achieve multicast communication. To set up our multicast server (lines 4 and 5), we first define the multicast group to which we belong and the port (in this case, “239.0.0.2”, 45002). Clients wanting to communicate with the server must also utilize this same group and port combination. Next, we create a typical datagram socket, at line 8, using the UDPSocket::new class method. We utilize the SO_REUSEADDR socket option (lines 11 and 12) in order to ensure that other clients (on the same host) can bind to this same group and port combination. Then at line 16, using the previously defined port number, we bind to the port number and Socket::INADDR_ANY (the wildcard interface).

Next, we enter the big loop, starting at line 22. Within this loop, we simply emit the current time at one second intervals to the multicast group (lines 25–26). Any clients having membership to this group and port will receive this time string. We emit the time string as would be done with any datagram server, specifying the string to send (Time::new:asctime), any flags, and, finally, the destination IP address and port (in this case, the multicast group and port number). The sleep method is used to wait for one second, and the process begins again by sending another time-string datagram. Finally, at line 34, we close the server socket using the close method.

Listing 20.6 Ruby Daytime multicast server.

start example
 1   require ‘socket’  2  3   # Multicast Group and Port  4   mcast_group = "239.0.0.2"  5   group_port = 45002  6  7   # Create a new UDP Socket  8   servsock = UDPSocket::new(Socket::AF_INET)  9 10   # Make the address/port association immediately reusable 11   servsock.setsockopt( Socket::SOL_SOCKET, 12                         Socket::SO_REUSEADDR, 1 ) 13 14   # Bind the server socket to the daytime port and 15   # any interface 16   servsock.bind( Socket::INADDR_ANY, group_port ) 17 18   # Debug data -- emit the server socket info 19   print("server address : ", servsock.addr::join(":"), "\n") 20 21   # The big loop 22   while true 23 24     # Emit the time through the socket to the client 25     servsock::send( Time::new::asctime+"\n", 0, 26                      mcast_group, group_port ) 27 28     # Wait one second 29     sleep 1 30 31   end 32 33   # Close the server socket 34   servsock.close 
end example

Multicast Client

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

After creating our UDP socket at line 8 (using the UDPSocket::new method), we make the address/port pair immediately reusable with the SO_REUSEADDR socket option (lines 11 and 12). At line 16, we use the bind method to permit our socket to accept datagrams from any port, and our previously defined multicast port (specified at line 5).

The next step is for the server to physically join the multicast group. This is performed using a socket option (IP_ADD_MEMBERSHIP), but before doing this, we must create a special address structure. The first step is creating a binary image of the IP address for which we want to join. Recall that our multicast group is “239.0.0.2”, so we create a binary array using the Array class and the pack method to create the binary equivalent (line 19). Lines 20 and 21 append another binary string representing the IP address of the current host. We first identify the host name for the host on which we’re executing using the Socket::gethostname method. This is used as an argument to Socket::gethostbyname, which communicates with the local resolver to resolve the host name to an IP address. Therefore, the variable mreq will represent a binary string containing eight bytes, four of the multicast group and four of the current host’s IP address. We then use this structure at lines 22 and 23 to actually join the multicast group using the setsockopt method.

Now that we’ve subscribed to the multicast group, we use the recv method at line 26 to receive a datagram from the group. Note that we use recv rather than recvfrom because we’re not interested in the source of the datagram (we know from whom it’s coming). We immediately emit the response datagram using the print method.

Finally, before we exit the client, we must remove ourselves from the multicast group. We use the setsockopt method again with IP_DROP_MEMBERSHIP to remove ourselves from the group (lines 29 and 30). The client socket is then closed using the close method (line 33).

Listing 20.7 Ruby Daytime multicast client.

start example
 1   require ‘socket’  2  3   # Multicast Group and Port  4   mcast_group = "239.0.0.2"  5   group_port = 45002  6  7   # Create a new UDP Socket  8   clisock = UDPSocket::new(Socket::AF_INET)  9 10   # Make the address/port association immediately reusable 11   clisock.setsockopt( Socket::SOL_SOCKET, 12                        Socket::SO_REUSEADDR, 1 ) 13 14   # Bind the client socket to the daytime port and 15   # any interface 16   clisock.bind( Socket::INADDR_ANY, group_port ) 17 18   # Join the multicast group 19   address = [239, 0, 0, 2].pack(‘CCCC’) 20   mreq = address + 21           Socket::gethostbyname(Socket::gethostname)[3] 22   clisock.setsockopt( Socket::IPPROTO_IP, 23                        Socket::IP_ADD_MEMBERSHIP, mreq ) 24 25   # Await receipt of the time from the server 26   print clisock.recv(100) 27 28   # Leave the multicast group 29   clisock.setsockopt( Socket::IPPROTO_IP, 30                        Socket::IP_DROP_MEMBERSHIP, mreq ) 31 32   # Close the client socket 33   clisock.close 
end example



 < 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