代码改变世界

网络编程之---广播和IP多播

2011-06-21 20:16  Clingingboy  阅读(2542)  评论(0编辑  收藏  举报

 

一.广播

1.接收

void main()
{
    SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);

    // 首先要绑定一个本地地址,指明广播端口号
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.S_un.S_addr = INADDR_ANY;    
    sin.sin_port = ::ntohs(4567);
    if(::bind(s, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
    {
        printf(" bind() failed \n");
        return;
    }

    // 接收广播
    printf(" 开始在4567端口接收广播数据... \n\n");
    SOCKADDR_IN addrRemote;    
    int nLen = sizeof(addrRemote);
    char sz[256];
    while(TRUE)
    {
        int nRet = ::recvfrom(s, sz, 256, 0, (sockaddr*)&addrRemote, &nLen);
        if(nRet > 0)
        {
            sz[nRet] = '\0';
            printf(sz);
        }
    }
}

2.发送

void main()
{
    SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);
    // 有效SO_BROADCAST选项
    BOOL bBroadcast = TRUE;
    ::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL));

    // 设置广播地址,这里的广播端口号(电台)是4567
    SOCKADDR_IN bcast;
    bcast.sin_family = AF_INET;
    bcast.sin_addr.s_addr = INADDR_BROADCAST; // ::inet_addr("255.255.255.255");
    bcast.sin_port = htons(4567);

    // 发送广播
    printf(" 开始向4567端口发送广播数据... \n \n");
    char sz[] = "This is just a test. \r\n";
    while(TRUE)
    {
        ::sendto(s, sz, strlen(sz), 0, (sockaddr*)&bcast, sizeof(bcast));
        ::Sleep(5000);
    }
}

二.IP多播

1.加入多播组并接收数据

void main()
{
    SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);

    // 允许其它进程使用绑定的地址
    BOOL bReuse = TRUE;
    ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&bReuse, sizeof(BOOL));


    // 绑定到4567端口
    sockaddr_in si;
    si.sin_family = AF_INET;
    si.sin_port = ::ntohs(4567);
    si.sin_addr.S_un.S_addr = INADDR_ANY;
    ::bind(s, (sockaddr*)&si, sizeof(si));
    
    // 加入多播组
    ip_mreq    mcast;
    mcast.imr_interface.S_un.S_addr = INADDR_ANY;
    mcast.imr_multiaddr.S_un.S_addr = ::inet_addr("234.5.6.7");  // 多播地址为234.5.6.7
    ::setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast, sizeof(mcast));


    // 接收多播组数据
    printf(" 开始接收多播组234.5.6.7上的数据... \n");
    char buf[1280];
    int nAddrLen = sizeof(si);
    while(TRUE)
    {
        int nRet = ::recvfrom(s, buf, strlen(buf), 0, (sockaddr*)&si, &nAddrLen);
        if(nRet != SOCKET_ERROR)
        {
            buf[nRet] = '\0';
            printf(buf);
        }
        else
        {
            int n = ::WSAGetLastError();
            break;
        }
    }
}

2.发送广播

同上

设置SO_REUSEADDR,则允许多个进程绑定到这个端号,这样加入到同个端口的组都可以接收到数据

三.源地址的IP多播

即可指定接收组内特定IP地址的消息

c#参考:http://www.cnblogs.com/xuhx/archive/2004/06/23/18150.html
http://www.cnblogs.com/xuhx/archive/2004/06/27/18960.html

Windows网络与通信程序设计 第5章