socket编程(3)广播 多播

广播

广播是指在一个局域网中向所有的网上节点发送信息。这是UDP连接的一种

广播有一个广播组,即只有一个广播组内的节点才能收到发往这个广播组的信息。什么决定了一个广播组呢,就是端口号,局域网内一个节点,如果设置了广播属性并监听了端口号A后,那么他就加入了A组广播,这个局域网内所有发往广播端口A的信息他都收的到。在广播的实现中,如果一个节点想接受A组广播信息,那么就要先将他绑定给地址和端口A,然后设置这个socket的属性为广播属性。如果一个节点不想接受广播信息,而只想发送广播信息,那么不用绑定端口,只需要先为socket设置广播属性后,向广播地址INADDR_BROADCAST的A端口发送udp信息即可。详细的程序实现如下:

1.初始化

    WSAStartup(MAKEWORD(2,2),&wsad);

2.创建一个UDP的socket
    s=socket(AF_INET,SOCK_DGRAM,0);

3.如果这个socket希望收到信息,则需要绑定地址和这组广播的端口号,如果只是希望发送广播信息,则不需要这步

    SOCKADDR_IN udpAdress,sender;
    int senferAddSize=sizeof(sender);
    udpAdress.sin_family=AF_INET;
    udpAdress.sin_port=htons(11114);
    udpAdress.sin_addr.s_addr=inet_addr("10.11.131.32");
    bind(s,(SOCKADDR*)&udpAdress,sizeof(udpAdress));

//这样这个节点即可收到局域网内所有发往端口11114的广播信息

4.设置socket的属性为广播
    bool optval=true;
    setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&optval,sizeof(bool));

5.下面就可以使用recvfrom或sendto来收发广播信息了

这里是接受,这是一个阻塞操作
            ret=recvfrom(s,data,1000,0,(SOCKADDR*)&sender,&senferAddSize);

这里是像该广播组发送信息,注意发送的地址为广播地址INADDR_BROADCAST,端口号为改组广播的端口号11114

    SOCKADDR_IN dstAdd;
    dstAdd.sin_family=AF_INET;
    dstAdd.sin_port=htons(11114);
    dstAdd.sin_addr.s_addr=INADDR_BROADCAST;
    sendto(s,data(),totalbyte,0,(SOCKADDR*)&dstAdd,sizeof(SOCKADDR));

 

多播

多播与广播不同,多播是指一条信息向局域网内有限几个节点传递,而广播是不管某个节点是否在制定组内,都会向这个节点发送广播信息,容易造成网络负担严重。

多播的实现是靠多播组,在局域网内,一个多播地址唯一的定义了一个多播组(端口号任意),可以使用的多播地址是有规定的,从224.0.0.0—239.255.255.255之间,但是其中的一些地址不能用,是用作特殊用途的:224.0.0.0 –224.0.0.2  224.0.1.1  224.0.0.9 224.0.1.24。一个节点如果想接受自某个多播组或向某个多播组发送信息,必须首先加入多播组,然后给予UDP发送。下面是详细的代码实现。

1.初始化

    WSAStartup(MAKEWORD(2,2),&wsad);

2.这里传建一个用于多播通信的socket,注意这个socket的参数为设置成多播
    s=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED);

3.将socket绑定到一个本地地址、端口,和广播不同,在多播中,无论是发送还是接收端都必须绑定一个本地地址,这个地址就是多播通信时处理信息的端口
    udpAdress.sin_family=AF_INET;
    udpAdress.sin_port=htons(22222);
    udpAdress.sin_addr.s_addr=inet_addr("10.11.131.32");
    bind(s,(SOCKADDR*)&udpAdress,sizeof(udpAdress));

4.定义多播组的地址
    multiCastGroup.sin_family=AF_INET;
    multiCastGroup.sin_port=htons(1111);此处端口任意,每个节点的可以设置成不同的
    multiCastGroup.sin_addr.s_addr=inet_addr("224.0.0.3"); 此处需使用上面规定地址段内的多播地址

5.加入这个多播组。注意这里的函数返回了一个socket,这个socket不负责通信,只是在脱离多播组时使用

    SOCKET sockM=WSAJoinLeaf(s,(SOCKADDR*)&multiCastGroup,sizeof(multiCastGroup),NULL,NULL,NULL,NULL,JL_BOTH);

6.下面使用recvfrom接受多播信息,或者使用sendto发送多播信息   

ret=recvfrom(s,data,1000,0,(SOCKADDR*)&sender,&senferAddSize);

sendto(s,data(),totalbyte,0,(SOCKADDR*)&multiCastGroup,sizeof(multiCastGroup));

7.最后关闭清理
    closesocket(sockM);
    closesocket(s);
    WSACleanup();

 

其他:

1)在多播组中,默认情况下一个发出多播信息的节点也会收到自己发送的信息,这称为多播回环,可以关闭多播回环:

bool val=false;

setsocket(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)val,sizeof(val));

2)在多播时,通常要设置适当的TTL(TTL的值是多少,那么多播信息就可以经过多少路由器,每经过一个路由器,TTl的值自动减1):

int val=3;

setsocket(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)val,sizeof(int));

你可能感兴趣的:(网络编程)