这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 广播与多播详解(一)

共3条 1/1 1 跳转至

广播与多播详解(一)

高工
2018-02-24 13:30:09     打赏

广播

广播是指在一个局域网中向所有的网上节点发送信息。这是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);




专家
2018-02-25 11:56:11     打赏
2楼

谢谢大神科普。


院士
2018-03-02 22:18:35     打赏
3楼

谢谢楼主的分享,学习了。


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]