组播程序的例子

       不知道为什么组播的等 级定义成三级,下面笔者只做自己加上一级便以讨论。

 

       Level 3   只接收多播组的数据而不向多播组发放数据,其实这就是一个Level 2的例子

                     只不过只是接收数据而一了,就像网络会议旁听者一样J

 

       下面只是列出两个例 子,读者可以根本这两个例子举一反三,编译环境要加上ws2_32.lib 还用到了以下的宏,可以放在文件的开始,或者放在单独的h文件。

   

    #define ReportErr(str)    \

        {   \

            printf("%s %d\n", __FILE__, __LINE__);  \

            printf("  %s  %d\n", str, GetLastError());   \

        }

   

    #define WSAReportErr(str) \

        {   \

            printf("%s %d\n", __FILE__, __LINE__);  \

            printf("  %s  %d\n", str, WSAGetLastError());   \

        }

   

    #define MC_ADDR     "234.5.6.7"

    #define MC_PORT     10000

    #define MAXLEN      256

 

一个Level 1例子

       只向多播组发送数据, 就像网络电视的Server

    #include <winsock2.h>

    #include <ws2tcpip.h>

   

    #include <stdio.h>

   

    void main(int argc, char **argv)

    {

        SOCKET          s;

        SOCKADDR_IN     mcAddr;

        int             nMcLen;

        int             n;

        char            buf[MAXLEN];

       

        WSADATA         wsaData;

        int             nErr;

       

        if(WSAStartup(0x0202, &wsaData) != 0)

        {

            ReportErr("WSAStartup(..)");

            return;

        };

       

        s = socket(AF_INET, SOCK_DGRAM, 0);

       

        if(s == INVALID_SOCKET)

        {

            WSAReportErr("socket(...)");

            WSACleanup();

            return;

        }

       

        mcAddr.sin_family       = AF_INET;

        mcAddr.sin_addr.s_addr  = inet_addr(MC_ADDR);

        mcAddr.sin_port         = htons(MC_PORT);

       

        nMcLen = sizeof(mcAddr);

       

        n = 0;

        while(1)

        {

            Sleep(1000);

           

            sprintf(buf, "This send to multicast group %s. seq: %d", MC_ADDR, n++);

           

            nErr = sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&mcAddr, nMcLen);

           

            if(nErr == SOCKET_ERROR)

            {

                WSAReportErr("sendto(...)");

                break;

            }

           

            printf("%s\n", buf);

        }

       

        WSACleanup();

    }

 

一个Level 3例子

    #include <winsock2.h>

    #include <ws2tcpip.h>

   

    #include <stdio.h>

    

    void main(int argc, char **argv)

    {

        SOCKET          s;

        SOCKADDR_IN     mcAddr;

        int             nMcLen;

   

        char            buf[MAXLEN];

       

        struct ip_mreq  ipmr;

   

        SOCKADDR_IN     localAddr;

           

        WSADATA         wsaData;

        int             nErr;

       

        if(WSAStartup(0x0202, &wsaData) != 0)

        {

            ReportErr("WSAStartup(..)");

            return;

        };

       

        s = socket(AF_INET, SOCK_DGRAM, 0);

       

        if(s == INVALID_SOCKET)

        {

            WSAReportErr("socket(...)");

            WSACleanup();

            return;

        }

       

        /* */

        memset(&localAddr, 0, sizeof(localAddr));

       

        localAddr.sin_family        = AF_INET;

        localAddr.sin_addr.s_addr   = htonl(INADDR_ANY)/*inet_addr(MC_ADDR)*/;

        localAddr.sin_port          = htons(MC_PORT);

       

        nErr = bind(s, (struct sockaddr*)&localAddr, sizeof(localAddr));

        if(nErr == SOCKET_ERROR)

        {

            WSAReportErr("bind(...)");

            WSACleanup();

            return;

        }

           

        /* Join multicast group */

        ipmr.imr_multiaddr.s_addr  = inet_addr(MC_ADDR);

        ipmr.imr_interface.s_addr  = htonl(INADDR_ANY);

       

        nErr = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&ipmr, sizeof(ipmr));

       

        if(nErr == SOCKET_ERROR)

        {

            WSAReportErr("setsockopt(.. IP_ADD_MEMBERSHIP ..)");

            WSACleanup();

            return;

        }

       

        mcAddr.sin_family       = AF_INET;

        mcAddr.sin_addr.s_addr  = inet_addr(MC_ADDR);

        mcAddr.sin_port         = htons(MC_PORT);

       

        nMcLen = sizeof(mcAddr);

   

        while(1)

        {

            Sleep(1000);

           

            nErr = recvfrom(s, buf, MAXLEN, 0, (struct sockaddr*)&mcAddr, &nMcLen);

           

            if(nErr == SOCKET_ERROR)

            {

                continue;

            }

           

            printf("%s\n", buf);

        }

       

        WSACleanup();

    }

参考书目

l         Multicast over TCP/IP HOWTO

Juan-manriano de Geyeneche jmseyas@dit.upm.es

l         ftp://ftp-eng.cisco.com/ipmulticast/

Cisco Co.

l         TCP/IP详解 1 2

W. Richard Stevens       , 译者: 范建华等

l         Windows网络编程(2)

Anthony Jones, Jim Ohlund, 译者: 杨合庆