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

The necessary function prototypes, types, and symbolic constants are imported in lines 1–5. Lines 7 and 8 define our addressing information. The MCAST_GROUP defines a multicast address, to which all clients and servers will be bound in order to send or receive datagrams. Additionally, a unique port (for UDP) must be specified for the host/port pair.

Listing 16.5 C language Daytime multicast server.

start example
 1   #include <stdio.h>  2   #include <sys/socket.h>  3   #include <arpa/inet.h>  4   #include <unistd.h>  5   #include <time.h>  6  7   #define MCAST_GROUP     "239.0.0.2"  8   #define MCAST_PORT      45002  9 10   int main () 11   { 12     int    sock, cnt, addrLen; 13     struct sockaddr_in addr; 14     char   buffer[512]; 15 16     sock = socket(AF_INET, SOCK_DGRAM, 0); 17 18     memset(&addr, 0, sizeof(addr)); 19     addr.sin_family = AF_INET; 20     addr.sin_port = htons(MCAST_PORT); 21     addr.sin_addr.s_addr = inet_addr(MCAST_GROUP); 22     addrLen = sizeof(addr); 23 24     while (1) { 25 26       time_t t = time(0); 27 28       sprintf(buffer, "%s\n", ctime(&t)); 29 30       printf("sending %s", buffer); 31 32       cnt = sendto(sock, buffer, strlen(buffer), 0, 33                     (struct sockaddr *)&addr, addrLen); 34 35       printf("cnt = %d\n", cnt); 36 37       sleep(1); 38 39     } 40 41     return 0; 42   }
end example

Our main application begins at line 10, and a number of necessary local variables are declared in lines 12–14.

At line 16, we create our server’s socket, specifying AF_INET for Internet communication and SOCK_DGRAM to identify UDP. The return value for the socket function is the socket descriptor.

The address structure for the server is initialized in lines 18–21. After clearing the structure in line 18, the family is set to AF_INET and the port is defined to our multicast port. At line 21, we initialize the address for which we’ll receive datagrams, in this case our multicast group address (MCAST_GROUP). Recall from Listing 16.3 that our datagram server provided INADDR_ANY for address, which permitted accepting datagrams on any available interface. Here, we specify our multicast address, which represents a special interface. We’ll discuss how to restrict these to one or more physical interfaces using the multicast socket options in the Multicast Client section.

At line 22, we compute the size of the address structure for use in the infinite loop (because it won’t change during the course of execution).

We begin our infinite loop at line 24. This multicast server simply emits the current time in string format every second. Because there is no connected state between multicast servers and clients, this arrangement will be used to discuss multicast dialogs.

At line 26, we capture the current time (using the standard time function) and then turn it into a string at line 28 using ctime. We emit this string (contained in buffer) to the console each time it’s generated just for debugging purposes.

At lines 32–33, we emit the previously constructed time string in buffer using a call to sendto. Note that we use the previously constructed socket descriptor, sock, along with the string buffer and its length as arguments 2 and 3. The fourth argument, flags, is unused in this example. Finally, we specify the address structure (addr) that represents the destination of the datagram and the address structure’s length (addrLen). From this single call, the datagram will be multicast to the defined group. This consists not only of applications on other hosts, but also of applications running on the same host that may have subscribed to the multicast group.

Finally, we emit the return value from the sendto call (line 35), which represents the number of bytes sent through to the multicast group. This should be identical to the string length of buffer. At line 37, we sleep one second and then continue the infinite loop at line 39.

Multicast Client

The C language source code for the multicast client is shown in Listing 16.6. 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.

Lines 1–18 are identical to the server listing in Listing 16.5, with the exception that the time.h header file is not used by the client. Lines 9–15 begin our C main program and provide some necessary variable declarations (we discuss the variables when used in the client application).

As with all socket-based applications, line 17 creates a new datagram socket for Internet communication. After the socket is created, we use the SO_REUSEADDR socket option to permit the port to be reused (lines 19–20). If this had not been done, the client would not have been able to bind the host/port pair to the socket, because another socket already exists with this port number (the server). By enabling the SO_REUSEADDR socket option, the Sockets API turns off this check and allows us to successfully bind to the port. The enable is defined by the on variable, which has been set to 1 to represent enable (0 represents disable). The SO_REUSEADDR option is a Sockets level option, so the SOL_SOCKET argument is specified.

In lines 22–25, we initialize the address structure that we want to bind to the previously created socket. After clearing the structure in line 22, we initialize the family for Internet communication and the port to the previously defined multicast port (MCAST_PORT). At line 25, the addr field is initialized to the wildcard INADDR_ANY to permit connections from any available interface. This information is then bound to the socket at line 27.

Next, in order to receive multicast datagrams, we must add our socket to the multicast membership group for the specific multicast group (lines 29–32). This action is performed through a setsockopt using the IP_ADD_MEMBERSHIP option. Within the mreq structure, we define the multicast group as the multicast address and the interface as the wildcard INADDR_ANY. This means that we’re registering to receive multicast traffic for our defined multicast group, and on any available host interface. We could set the interface to a single interface (if the host were multi-homed) and restrict the receipt of multicast traffic to a single interface. Recall from Listing 16.5 that the server does not perform this socket option. This is because adding a socket to multicast membership is only required to receive multicast datagrams. Multicast datagrams can be sent without membership.

Finally, the client enters an infinite loop in lines 34–44 to receive multicast datagrams from the server. Datagram receipt is performed using the recvfrom call. Although knowing who sent the datagram is not necessary in this example (from the addr structure), we use this information to emit the source along with the time string (line 42). Note that the sockaddr_in structure (addr) is reused in this example; the information specified in lines 23–25 is not relevant to the recvfrom call at line 38.

Listing 16.6 C language Daytime multicast client.

start example
  1   #include <stdio.h>  2   #include <sys/socket.h>  3   #include <arpa/inet.h>  4   #include <unistd.h>  5  6   #define MCAST_GROUP     "239.0.0.2"  7   #define MCAST_PORT      45002  8  9   int main () 10   { 11     int    sock, cnt, addrlen; 12     int    on=1; 13     struct sockaddr_in addr; 14     struct ip_mreq mreq; 15     char   buffer[512]; 16 17     sock = socket(AF_INET, SOCK_DGRAM, 0); 18 19     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 20                 (char *)&on, sizeof(on)); 21 22     memset(&addr, 0, sizeof(addr)); 23     addr.sin_family = AF_INET; 24     addr.sin_port = htons(MCAST_PORT); 25     addr.sin_addr.s_addr = htonl(INADDR_ANY); 26 27     bind(sock, (struct sockaddr *)&addr, sizeof(addr)); 28 29     mreq.imr_multiaddr.s_addr = inet_addr(MCAST_GROUP); 30     mreq.imr_interface.s_addr = htonl(INADDR_ANY); 31     setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 32                 &mreq, sizeof(mreq)); 33 34     while (1) { 35 36       addrlen = sizeof(addr); 37 38       cnt = recvfrom(sock, buffer, sizeof(buffer), 0, 39                       (struct sockaddr *)&addr, &addrlen); 40       buffer[cnt] = 0; 41 42       printf("%s : %s\n", inet_ntoa(addr.sin_addr), buffer); 43 44     } 45 46     return 0; 47   }
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