Multicasting



Ø     Receiving Multicast Messages

Ø     Sending Multicast Message

Ø     Multicast Control

Ø     Multicast Examples

Ø     Displaying Destination Address

 

 

 

 


ü   Receiving Multicast Message

For a process to recieve multicast messages it needs to perform the following steps:

v Craeate a UDP socket sd

sd = socket (PF_INET,SOCK_DGRAM, 0);

 

v Bind it to a UDPport, e.g., 10123.



 struct   sockaddr_in   LocalAddress;

#define SA      struct  sockaddr;

 

 

 LocalAddress.sin_family = AF_INET;
 LocalAddress.sin_port = htons( UDPport);
 LocalAddresst.sin_addr.s_addr  =  htonl (INADDR_ANY);

 bind (sd,  (SA *) &LocalAddress, sizeof(LocalAddress));

 

v All processes must bind to the same port   in order to receive the multicast messages.

Thus all must use before binding.

reusePort (sd);

 

v Join a multicast IP address MulticatIPAddress ,  e.g., 224.111.112.113

 

joinGroup (sd, MulticastIPAddress);

 

v Use recv or recvfrom to read the messages, e.g.,

 

nbytes = recv (sd, recvBuf, sizeof(recvBuf), 0);

 

 

 

 

 


ü   Sendinging Multicast Message

 

For a process to send multicast messages it needs to perform the following:

You may use the same UD Psocket  sd  for sending as well as receiving multicast messages or

you can use  any udp socket (it does not have to join any multicast group).

 

Declare and fill-in  the address MulticatGroupAddress:

   struct  sockaddr_in    MulticatGroupAddress;

   MulticatGroupAddress.sin_family = AF_INET;
   MulticatGroupAddress.sin_port =  UDPport;
   MulticatGroupAddress.sin_addr.s_addr = inet_addr (MulticatIPAddress);

   sendto (sd, sendBuf, Len,0,  (SA *) &MulticastGroupAddress, sizeof(MulticastGroupAddress)) ;

 

 

 

 


ü   Multicast Control Utility:

 

Join Group:

To join a udp socket sd to multicast IP address in the range: 224.0.0.0 through 239.255.255.255 use:

 

joinGroup (sd, “224.0.0.1”);

Time-to-live:

To control how far the messages can go,
e.g., 2 means at most 2 routers away.
 

u_char   TimeToLive;
TimeToLive = 2;

setTTLvalue (sd,  &TimeToLive);


Loop-back:

To allow the process to get a copy of its own transmission we use:

u_char loop;
loop = 1;

setLoopback (sd,  &loop);

Reuse-port:

To allow multiple multicast processes to run on the same host:

reusePort (sd);

 

 

  

 

 


  

ü   Multicast Examples

 

ü     Group Chat

 Usage: mcastChat <mcastIPAddress>  <port>

        E.g: % mcastChat  224.0.0.22  10022

 

 

 

ü     Textbook Example:    (chapter 21):

 

        Usage: sendrecv  <maddr>   <port>

        E.g: % sendrecv  224.0.0.33    10123 
  

 

 


ü   Displaying Destination Address

 

 

 

 

Description: msgHeader

 

ü   Example: DisplayDistAddr.c

 

struct msghdr   mhdr;
struct iovec    iov;
char            data[8192];
char            cdata[sizeof(struct sockaddr_in) + sizeof(struct cmsghdr)];
struct cmsghdr *cmsg;
struct sockaddr_in from;
socklen_t       fromlen = sizeof(struct sockaddr_in);
struct in_addr  ip_addr;
struct cmsghdr *cmptr;
char            str[32];

int
main(int argc, char **argv)
{

    int             echo_s;
    struct sockaddr_in laddr;
    int             ret;
    int             loop;

    if (argc < 2) {
         printf("usage: udpServerDaddr <group IP> <local_port>\n");
         exit(0);
    }
    echo_s = socket(AF_INET, SOCK_DGRAM, 0);
    reusePort(echo_s);

    bzero(&laddr, sizeof(laddr));
    laddr.sin_family = AF_INET;
    laddr.sin_port = htons(atoi(argv[2]));
    if (bind(echo_s, (struct sockaddr *) & laddr, sizeof(laddr)) < 0) {
         perror("bind error");
         exit(1);
    }
    displayDaddr(echo_s);

    joinGroup(echo_s, argv[1]);

    loop = 0;
    setLoopback(echo_s, loop);


    while (1) {

/*  using recvmsg &  sendmsg */
printf("\n.... Using recvMSG & sendMSG ....\n");
         init_mhdr();
         if ((ret = recvmsg(echo_s, &mhdr, MSG_WAITALL)) < 0) {
             perror("recvmsg()");
         }
         printf("received:");
         fflush(stdout);
         write(1, data, ret);
         display_addr();

         iov.iov_len = ret;
         if (sendmsg(echo_s, &mhdr, MSG_DONTWAIT) < 0) {
             perror("sendmsg()");
             exit(-1);
         }
/*  using recvfrom & sendto */
printf("\n.... Using recvFROM & sendTO ....\n");
         if ((ret = recvfrom(echo_s, data, sizeof(data), 0,
             (SA *) & from, &fromlen)) < 0) {
             perror("recvfrom");
         }
         printf("received:");
         fflush(stdout);
         write(1, data, ret);
         printf("udp message sent  from: %s:%d\n",
                        inet_ntop(AF_INET, &from.sin_addr, str, sizeof(str)),
             ntohs(from.sin_port));

         if (sendto(echo_s, data, ret, 0, (SA *) & from, fromlen) < 0) {
             printf("error in sendto\n");
             exit(-1);
         }
    }
}
void
init_mhdr()
{
    bzero(cdata, sizeof(cdata));
    bzero(&mhdr, sizeof(mhdr));
    mhdr.msg_name = &from;
    mhdr.msg_namelen = fromlen;
    mhdr.msg_iov = &iov;
    mhdr.msg_iovlen = 1;
    mhdr.msg_control = cdata;
    mhdr.msg_controllen = sizeof(cdata);
    iov.iov_base = data;
    iov.iov_len = sizeof(data);
    cmsg = (struct cmsghdr *) cdata;
}

void
display_addr()
{

    for (cmptr = CMSG_FIRSTHDR(&mhdr); cmptr != NULL;
         cmptr = CMSG_NXTHDR(&mhdr, cmptr)) {
         if (cmptr->cmsg_level == IPPROTO_IP &&
             cmptr->cmsg_type == IP_RECVDSTADDR) {
             memcpy(&ip_addr, CMSG_DATA(cmptr), sizeof(struct in_addr));
             printf("udp message sent  to: %s\n",
             inet_ntop(AF_INET, &ip_addr, str, sizeof(str)));
             printf("udp message sent  from: %s:%d\n",
             inet_ntop(AF_INET, &from.sin_addr, str,
                      sizeof(str)), ntohs(from.sin_port));
         }
    }
}
 

 

 

To test:

 

·       Server:

% cd   ~/mcastChat

%  DisplayDistAddr   224.0.0.1  10123

 

·       Client:

% cd   ~/mcastChat
% mcastChat    224.0.0.1   10123

 

Notice the  change of behavior  when  start one program  before the  other !