柚子快報(bào)邀請(qǐng)碼778899分享:網(wǎng)絡(luò)協(xié)議 網(wǎng)絡(luò) UDP多播
一、多播概念
1.1、多播
? ? ? ? 多播又稱為:組播。 一個(gè)人發(fā)數(shù)據(jù),只有加入到多播組的人接收數(shù)據(jù)
1.2、多播的特點(diǎn)
? ? 1、多播地址標(biāo)示一組接口 ? ? 2、多播可以用于廣域網(wǎng)使用 ? ? 3、在IPv4中,多播是可選的
1.3、多播地址?
IPv4的D類地址是多播地址 十進(jìn)制:224.0.0.1~239.255.255.254 十六進(jìn)制:E0.00.00.01~EF.FF.FF.FE
?組播地址是分類編址的IPv4地址中的D類地址,又叫多播地址,他的前四位必須是1110,多播組的地址是D類IP,規(guī)定是224.0.0.0——239.255.255.255。
1.4、多播ip地址用處
224.0.0.0~224.0.0.255為預(yù)留的組播地址(永久組地址),地址224.0.0.0保留不做分配,其它地址供路由協(xié)議使用
224.0.1.0~224.0.1.255是公用組播地址,可以用于Internet
224.0.2.0~238.255.255.255為用戶可用的組播地址(臨時(shí)組地址),全網(wǎng)范圍內(nèi)有效
239.0.0.0~239.255.255.255為本地管理組播地址,僅在特定的本地范圍內(nèi)有效
1.5、多播地址向以太網(wǎng)MAC地址的映射
1.5.1、計(jì)算多播mac地址(mac地址占48位)
解題方法:組播地址MAC以01-00-5e開頭(規(guī)定的),占25bit。由于MAC地址是48bit,而IP地址有32bit,因此需要從ip地址獲取后23位。如何獲取,最安全的又準(zhǔn)確的方法:就是把IP地址,換成二進(jìn)制數(shù)。第2個(gè)8位中的第1位規(guī)定為0,去掉前8位,再把剩下的二進(jìn)制換成16進(jìn)制,最后添加在01-00-5e后面即可
舉例說明 例如 1、求224.128.129.130的組播MAC過程如下:
第一步:我們可以永遠(yuǎn)都知道多播mac地址前25位,都是01-00-5e(規(guī)定的)。
第二步:把ip地址化為二進(jìn)制?
? ? ? ? 224.128.129.130的二進(jìn)制形式
? ? 1110 0000?1000 0000 1000 0001? 1000 0010? 把第2個(gè)8位中的第1位規(guī)定為0,即紅色的1改為0
得:??1110 0000?0000 0000 1000 0001? 1000 0010? 把前8位去掉,即黑色部分去掉
得:??0000 0000 1000 0001? 1000 0010??
第三步:把得出的二進(jìn)制轉(zhuǎn)化成16進(jìn)制(0000 0000 1000 0001? 1000 0010??)
得:??00-81-82
第三步:合并
該ip的組播mac地址:01-00-5e-00-81-82
二、多播工作過程
多播不需要設(shè)置setsockopt(套接字選項(xiàng))
比起廣播,多播具有可控性,只有加入多播組的接收者才可以接收數(shù)據(jù),否則接收不到
?2.1、分析發(fā)送端設(shè)置流程
?第一步:創(chuàng)建套接字——socket函數(shù)
第二步:設(shè)置為UDP協(xié)議和端口號(hào)(此端口為 對(duì)方的端口號(hào) )
第三步:設(shè)置IPV4,由于使用的是多播,需要把ip地址 設(shè)為多播地址.
? ? ? ? ? ? ? 多播地址范圍:224.0.0.0——239.255.255.255。
第四步:設(shè)置傳輸為以太網(wǎng),mac地址根據(jù)ip地址? (轉(zhuǎn)看1.5示例)
2.2、分析如何傳輸與接收
第一步:把打包好數(shù)據(jù)包,發(fā)送到多播組里。
第二步:接收者想要接收到信息,必須要先加入多播組里
三、多播代碼流程
發(fā)送者: 第一步:創(chuàng)建套接字 socket() 第二步:向多播地址發(fā)送數(shù)據(jù) sendto()
接收者: 第一步:創(chuàng)建套接字 socket() 第二步:設(shè)置為加入多播組 setsockopt()第三步:將套接字與多播信息結(jié)構(gòu)體綁定 bind() 第五步:接收數(shù)據(jù)
四、多播地址結(jié)構(gòu)
在IPv4因特網(wǎng)域(AF_INET)中,多播地址結(jié)構(gòu)體用如下結(jié)構(gòu)體ip_mreq表示
?五、多播套接口選項(xiàng)(接收者需要使用此函數(shù)加入多播組)
頭文件
? ? ? ? ? ? #include
? ?int setsockopt(int socket, int level, int option_name,const void *option_value, socklen_t option_len); 功能:
? ? ? ? ? ?設(shè)置一個(gè)套接字的選項(xiàng)(屬性) 參數(shù): ? ? ? ? ? ? socket:文件描述符 ? ? ? ? ? ? level:協(xié)議層次 ? ? ? ? ? ? ? ? ? ? ? ? ?IPPROTO_IP IP層次 ? ? ? ? ? ?option_name:選項(xiàng)的名稱 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?IP_ADD_MEMBERSHIP 加入多播組 ? ? ? ? ? ?option_value:設(shè)置的選項(xiàng)的值
結(jié)構(gòu)體 ? ? ? ? ? struct ip_mreq ?{ ? ? ? ? struct in_addr imr_multiaddr; //組播ip地址 ? ? ? ? struct in_addr imr_interface; //主機(jī)地址 ? ? ? ? INADDR_ANY 任意主機(jī)地址(自動(dòng)獲取你的主機(jī)地址) ? ? ? ? }; ? ? ? ? ? ?option_len:option_value的長度 ?返回值: ? ? ? ? ? ? ? ?成功:0 ? ? ? ? ? ? ? ?失?。憨\1
多播設(shè)置
? ? mreq.imr_multiaddr.s_addr=inet_addr(argv[1]); ?? ?mreq.imr_interface.s_addr=INADDR_ANY;//? ? ? ? INADDR_ANY獲取自己的ip地址 ?? ?socklen_t optlen =sizeof(mreq);
?? ?if(setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,optlen) < 0) ?? ?{ ?? ??? ?perror("fail to setsockopt"); ?? ??? ?exit(1); ?? ??? ?}
5.1、發(fā)送者(代碼)
#include
#include
#include
#include
#include
#include
#include
int main(int argc ,char *argv[])
{
if(argc<3)
{
printf("error lose ip port\n");
exit(1);
}
int sockfd;
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
struct sockaddr_in mysockaddr;
mysockaddr.sin_family = AF_INET;
mysockaddr.sin_port =htons(atoi(argv[2]));
mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
socklen_t addrlen= sizeof(mysockaddr);
char buf[128];
while(1)
{
fgets(buf,sizeof(buf),stdin);
if(sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&mysockaddr,addrlen)==-1)
{
perror("fail to sendto");
exit(1);
}
}
close(sockfd);
return 0;
}
?5.2、接收者(代碼)
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc ,char *argv[])
{
if(argc<3)
{
printf("input fail lose ip port");
exit(1);
}
int sockfd;
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr=inet_addr(argv[1]);
mreq.imr_interface.s_addr=INADDR_ANY;
socklen_t optlen =sizeof(mreq);
if(setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,optlen) < 0)
{
perror("fail to setsockopt");
exit(1);
}
struct sockaddr_in mysockaddr;
mysockaddr.sin_family = AF_INET;
mysockaddr.sin_port =htons(atoi(argv[2]));
mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
socklen_t addrlen= sizeof(mysockaddr);
if(bind(sockfd,(struct sockaddr *)&mysockaddr,addrlen)==-1)
{
perror("fail to bind");
exit(1);
}
char buf[128];
struct sockaddr_in sendsockaddr;
socklen_t sendaddrlen=sizeof(sendsockaddr);
while(1)
{
if(recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&sendsockaddr,&sendaddrlen)==-1)
{
perror("fail to recvfrom");
exit(1);
}
printf("[%s ‐ %d]: %s\n", inet_ntoa(sendsockaddr.sin_addr), ntohs(sendsockaddr.sin_port),buf);
}
close(sockfd);
return 0;
}
運(yùn)行結(jié)果
?多播地址范圍:224.0.0.0——239.255.255.255。
我設(shè)置了多播組地址為:224.0.0.2 端口號(hào)為8081
只要加入了224.0.0.2多播組地址并且端口號(hào)為8081的客戶端,服務(wù)器綁定的多播組224.0.0.2都會(huì)接收到客戶端發(fā)來的數(shù)據(jù)。
柚子快報(bào)邀請(qǐng)碼778899分享:網(wǎng)絡(luò)協(xié)議 網(wǎng)絡(luò) UDP多播
推薦鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。