Thread: IPv6 multicast example code

  1. #1
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072

    IPv6 multicast example code

    I've just installed IPv6 and connected myself to the IPv6 Internet with Windows XP. Now I want to write some programs.

    I'm having trouble finding example code for IPv6 multicast. What I want is something like <http://www.ipmulticast.com/content/category/4/72/30/ >, but for IPv6 instead of IPv4.

    Has anyone here programmed for IPv6?
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    MSDN has a good guide for making IPv6 compatible applications. Anyway, it looked like an interesting challenge, so:
    Code:
    /* multicast_server.c
     * This sample demonstrates a Windows multicast server that works with either
     * IPv4 or IPv6, depending on the multicast address given.
     * Requires Windows XP+/Use MSVC and platform SDK to compile.
     * Troubleshoot: Make sure you have the IPv6 stack installed by running
     *     >ipv6 install
     *
     * Usage:
     *     multicast_server multicastip port data [ttl]
     *
     * Examples:
     *     >multicast_server 224.0.22.1 9210 HelloIPv4World
     *     >multicast_server ff15::1 2001 HelloIPv6World
     *
     * Written by tmouse, July 2005
     * http://cboard.cprogramming.com/showthread.php?t=67469
     */
    
    #include <stdio.h>      /* for fprintf() */
    #include <winsock2.h>   /* for socket(), connect(), send(), and recv() */
    #include <ws2tcpip.h>   /* for ip options */
    #include <stdlib.h>     /* for atoi() and exit() */
    
    #if defined(_MSC_VER)
    #pragma comment(lib, "ws2_32.lib")
    #endif
    
    
    static void DieWithError(char* errorMessage)
    {
        fprintf(stderr, "%s\n", errorMessage);
        exit(EXIT_FAILURE);
    }
    
    
    int main(int argc, char *argv[])
    {
        SOCKET    sock;                   /* Socket */
        WSADATA   wsaData;                /* For WSAStartup */
        char*     multicastIP;            /* Arg: IP Multicast address */
        char*     multicastPort;          /* Arg: Server port */
        char*     sendString;             /* Arg: String to multicast */
        size_t    sendStringLen;          /* Length of string to multicast */
        DWORD     multicastTTL;           /* Arg: TTL of multicast packets */
        ADDRINFO* multicastAddr;          /* Multicast address */
        ADDRINFO  hints          = { 0 }; /* Hints for name lookup */
    
        if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        {
            DieWithError("WSAStartup() failed");
        }
    
        if ( argc < 4 || argc > 5 )
        {
            fprintf(stderr, "Usage:  %s <Multicast Address> <Port> <Send String> [<TTL>]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        multicastIP   = argv[1];             /* First arg:   multicast IP address */
        multicastPort = argv[2];             /* Second arg:  multicast port */
        sendString    = argv[3];             /* Third arg:   String to multicast */
        multicastTTL  = (argc == 5 ?         /* Fourth arg:  If supplied, use command-line */
                         atoi(argv[4]) : 1); /* specified TTL, else use default TTL of 1 */
        sendStringLen = strlen(sendString);  /* Find length of sendString */
    
        /* Resolve destination address for multicast datagrams */
        hints.ai_family   = PF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags    = AI_NUMERICHOST;
        if ( getaddrinfo(multicastIP, multicastPort, &hints, &multicastAddr) != 0 )
        {
            DieWithError("getaddrinfo() failed");
        }
    
        printf("Using %s\n", multicastAddr->ai_family == PF_INET6 ? "IPv6" : "IPv4");
    
        /* Create socket for sending multicast datagrams */
        if ( (sock = socket(multicastAddr->ai_family, multicastAddr->ai_socktype, 0)) == INVALID_SOCKET )
        {
            DieWithError("socket() failed");
        }
    
        /* Set TTL of multicast packet */
        if ( setsockopt(sock,
                        multicastAddr->ai_family == PF_INET6 ? IPPROTO_IPV6        : IPPROTO_IP,
                        multicastAddr->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL,
                        (char*) &multicastTTL, sizeof(multicastTTL)) != 0 )
        {
            DieWithError("setsockopt() failed");
        }
    
        for (;;) /* Run forever */
        {
            if ( sendto(sock, sendString, sendStringLen, 0,
                        multicastAddr->ai_addr, multicastAddr->ai_addrlen) != sendStringLen )
            {
                DieWithError("sendto() sent a different number of bytes than expected");
            }
    
            Sleep(3000); /* Multicast sendString in datagram to clients every 3 seconds */
        }
    
        /* NOT REACHED */
        freeaddrinfo(multicastAddr);
        closesocket(sock);
        return 0;
    }
    Code:
    /* multicast_client.c
     * This sample demonstrates a Windows multicast client that works with either
     * IPv4 or IPv6, depending on the multicast address given.
     * Requires Windows XP+/Use MSVC and platform SDK to compile.
     * Troubleshoot: Make sure you have the IPv6 stack installed by running
     *     >ipv6 install
     *
     * Usage:
     *     multicast_client multicastip port
     *
     * Examples:
     *     >multicast_client 224.0.22.1 9210
     *     >multicast_client ff15::1 2001
     *
     * Written by tmouse, July 2005
     * http://cboard.cprogramming.com/showthread.php?t=67469
     */
     
    #include <stdio.h>      /* for printf() and fprintf() */
    #include <winsock2.h>   /* for socket(), connect(), sendto(), and recvfrom() */
    #include <ws2tcpip.h>   /* for ip_mreq */
    #include <stdlib.h>     /* for atoi() and exit() */
    #include <string.h>     /* for memset() */
    #include <time.h>       /* for timestamps */
    
    #if defined(_MSC_VER)
    #pragma comment(lib, "ws2_32.lib")
    #endif
    
    
    void DieWithError(char* errorMessage)
    {
        fprintf(stderr, "%s\n", errorMessage);
        exit(EXIT_FAILURE);
    }
    
    
    int main(int argc, char* argv[])
    {
        SOCKET     sock;                     /* Socket */
        WSADATA    wsaData;                  /* For WSAStartup */
        char*      multicastIP;              /* Arg: IP Multicast Address */
        char*      multicastPort;            /* Arg: Port */
        ADDRINFO*  multicastAddr;            /* Multicast Address */
        ADDRINFO*  localAddr;                /* Local address to bind to */
        ADDRINFO   hints          = { 0 };   /* Hints for name lookup */
    
        if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        {
            DieWithError("WSAStartup() failed");
        }
    
        if ( argc != 3 )
        {
            fprintf(stderr,"Usage: %s <Multicast IP> <Multicast Port>\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        multicastIP   = argv[1];      /* First arg:  Multicast IP address */
        multicastPort = argv[2];      /* Second arg: Multicast port */
    
        /* Resolve the multicast group address */
        hints.ai_family = PF_UNSPEC;
        hints.ai_flags  = AI_NUMERICHOST;
        if ( getaddrinfo(multicastIP, NULL, &hints, &multicastAddr) != 0 )
        {
            DieWithError("getaddrinfo() failed");
        }
    
        printf("Using %s\n", multicastAddr->ai_family == PF_INET6 ? "IPv6" : "IPv4");
    
        /* Get a local address with the same family (IPv4 or IPv6) as our multicast group */
        hints.ai_family   = multicastAddr->ai_family;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags    = AI_PASSIVE; /* Return an address we can bind to */
        if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 )
        {
            DieWithError("getaddrinfo() failed");
        }
    
        /* Create socket for receiving datagrams */
        if ( (sock = socket(localAddr->ai_family, localAddr->ai_socktype, 0)) == INVALID_SOCKET )
        {
            DieWithError("socket() failed");
        }
    
        /* Bind to the multicast port */
        if ( bind(sock, localAddr->ai_addr, localAddr->ai_addrlen) != 0 )
        {
            DieWithError("bind() failed");
        }
    
        /* Join the multicast group. We do this seperately depending on whether we
         * are using IPv4 or IPv6. WSAJoinLeaf is supposed to be IP version agnostic
         * but it looks more complex than just duplicating the required code. */
        if ( multicastAddr->ai_family  == PF_INET &&  
             multicastAddr->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */
        {
            struct ip_mreq multicastRequest;  /* Multicast address join structure */
    
            /* Specify the multicast group */
            memcpy(&multicastRequest.imr_multiaddr,
                   &((struct sockaddr_in*)(multicastAddr->ai_addr))->sin_addr,
                   sizeof(multicastRequest.imr_multiaddr));
    
            /* Accept multicast from any interface */
            multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
    
            /* Join the multicast address */
            if ( setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 )
            {
                DieWithError("setsockopt() failed");
            }
        }
        else if ( multicastAddr->ai_family  == PF_INET6 &&
                  multicastAddr->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */
        {
            struct ipv6_mreq multicastRequest;  /* Multicast address join structure */
    
            /* Specify the multicast group */
            memcpy(&multicastRequest.ipv6mr_multiaddr,
                   &((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr,
                   sizeof(multicastRequest.ipv6mr_multiaddr));
    
            /* Accept multicast from any interface */
            multicastRequest.ipv6mr_interface = 0;
    
            /* Join the multicast address */
            if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 )
            {
                DieWithError("setsockopt() failed");
            }
        }
        else
        {
            DieWithError("Neither IPv4 or IPv6");
        }
    
        freeaddrinfo(localAddr);
        freeaddrinfo(multicastAddr);
    
        for (;;) /* Run forever */
        {
            time_t timer;
            char   recvString[500];      /* Buffer for received string */
            int    recvStringLen;        /* Length of received string */
    
            /* Receive a single datagram from the server */
            if ( (recvStringLen = recvfrom(sock, recvString, sizeof(recvString) - 1, 0, NULL, 0)) < 0 )
            {
                DieWithError("recvfrom() failed");
            }
    
            recvString[recvStringLen] = '\0';
    
            /* Print the received string */
            time(&timer);  /* get time stamp to print with recieved data */
            printf("Time Received: %.*s : %s\n", strlen(ctime(&timer)) - 1, ctime(&timer), recvString);
        }
    
        /* NOT REACHED */
        closesocket(sock);
        exit(EXIT_SUCCESS);
    }
    I'm not connected to an IPv6 network so I've only tested it locally.

  3. #3
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Thanks, I'm going to test your code later on.

    I managed to write an application which worked locally on one computer. I'm having trouble with the connection to the 6bone on my other computer, so I'm not able to test it globally either.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  4. #4
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Hmm, when I use the address ff15::1 I recieve each datagram two times on my laptop (SP2 Home), but when I try the same program on my stationary (SP2 Prof) I recieve each datagram only once.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  5. #5
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    I'm using freenet6 and I have been assigned a /48 prefix. One stationary computer is a router which advertises addresses to every computer on the local network.

    It seems to be working -- if I go to www.ipv6.org with my laptop it shows
    You are using IPv6 from 2001:5c0:89fb:0:20e:35ff:fe54:78af
    Now, if I want to use global multicast, which address should I use? According to this document, http://www.ipv6style.jp/en/tech/2004...041001_p.shtml , it seems that you can create a multicast address from your prefix.

    So if my prefix is 2001:5c0:89fb, could I use ff3e:20:2001:5c0:89fb :: 1 as a multicast address? It doesn't seem to be working.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  6. #6
    Registered User Jaqui's Avatar
    Join Date
    Feb 2005
    Posts
    416
    from chapter 25 of tcip with ipv6:

    IPv6 Supported Address Types
    One important change in the addressing model of IPv6 is the address types supported.
    IPv4 supported three address types: unicast, multicast, and broadcast. Of these,
    the vast majority of actual traffic was unicast. IP multicast support was not widely
    deployed until many years after the Internet was established and it continues to be
    hampered by various issues. Use of broadcast in IP had to be severely restricted for
    performance reasons (we don’t want any device to be able to broadcast across the
    entire Internet!).
    IPv6 also supports three address types, but with the following changes:
    Unicast Addresses These are standard unicast addresses as in IPv4, one per host
    interface.
    Multicast Addresses These are addresses that represent various groups of IP
    devices. A message sent to a multicast address goes to all devices in the group. IPv6
    includes much better multicast features and many more multicast addresses than
    IPv4. Since multicast under IPv4 was hampered in large part due to lack of support
    of the feature by many hardware devices,
    support for multicasting is a required, not
    optional, part of IPv6.
    Anycast Addresses Anycast addressing is used when a message must be sent to any
    member of a group, but does not need to be sent to all of them. Usually the member
    of the group that is easiest to reach will be sent the message. One common
    example of how anycast addressing could be used is in load sharing among a group
    of routers in an organization.
    Broadcast addressing as a distinct addressing method is gone in IPv6. Broadcast
    functionality is implemented using multicast addressing to groups of devices. A
    multicast group to which all nodes belong can be used for broadcasting in a network,
    for example.
    KEY CONCEPT IPv6 has unicast and multicast addresses like IPv4. There is, however, no
    distinct concept of a broadcast address in IPv6. A new type of address, the anycast address, has
    been added to allow a message to be sent to any one member of a group of devices.
    it may be your device causing the problem.

    for the addressing part:

    Table 25-1: IPv6 Address Space Allocations
    Leading Bits
    Fraction of Total
    IPv6 Address Space Allocation
    0000 0000 1/256 Unassigned (Includes special addresses such as the
    unspecified and loopback addresses)
    0000 0001 1/256 Unassigned
    0000 001 1/128 Reserved for NSAP address allocation
    0000 01 1/64 Unassigned
    0000 1 1/32 Unassigned
    0001 1/16 Unassigned
    001 1/8 Global unicast addresses
    010 1/8 Unassigned
    011 1/8 Unassigned
    100 1/8 Unassigned
    101 1/8 Unassigned
    110 1/8 Unassigned
    1110 1/16 Unassigned
    1111 0 1/32 Unassigned
    1111 10 1/64 Unassigned
    1111 110 1/128 Unassigned
    1111 1110 0 1/512 Unassigned
    1111 1110 10 1/1024 Link-local unicast addresses
    1111 1110 11 1/1024 Site-local unicast addresses
    1111 1111 1/256 Multicast addresses
    from same source.

    hope this helps you solve the problem

  7. #7
    Registered User Jaqui's Avatar
    Join Date
    Feb 2005
    Posts
    416
    the second quote is actually table data, sorry that the formatting makes it hard to follow.

  8. #8
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    They don't mean user hardware devices -- they mean routers on the Internet. It is easy for a client to support multicast, but harder for routers.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sockets: IPv4 vs IPv6
    By ninboy in forum Networking/Device Communication
    Replies: 1
    Last Post: 10-15-2008, 01:02 AM
  2. Proposal: Code colouring
    By Perspective in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 05-14-2007, 07:23 AM
  3. Values changing without reason?
    By subtled in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 10:20 AM
  4. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM