组播
1> 组播也是实现一对多的通信方式,对于广播而言,网络需要对每个消息进行复制转发,会占用大量的带宽,导致网络拥塞
2> 组播可以实现小范围的数据传播:将需要接收数据的接收端加入多播组,发送端向多播组中发送消息,每个组内成员都能接收到消息
3> 需要对接收端进行设置,将接收端加入多播组
1、需要使用setsockopt函数实现
2、需要对网络层设置:IPPROTO_IP
3、需要对加入多播组属性设置:IP_ADD_MEMBERSHIP
4、属性值的类型
struct ip_mreqn {
struct in_addr imr_multiaddr; /* 组播地址:D类网络(224.0.0.0 --- 239.255.255.255) */ struct
in_addr imr_address; /* 当前主机IP地址 */
int imr_ifindex; /* 网卡编号: 通过指令 ip ad查看 */
};
4> 组播也是使用UDP实现的,无论接收端是否愿意接收数据,发送端都可以正常向多播组中发送数据
5> 组播也分为发送端和接收端流程
组播发送端流程 -----> 类似于UDP的客户端流程
1、socket(); //创建用于通信的套接字文件描述符
2、bind(); //可选,可以绑定也可以不绑定
3、sendto(); //向多播组地址发送消息
4、close(); //关闭套接字
#include<myhead.h>
int main(int argc, const char *argv[])
{
//创建socket
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd ==-1)
{
perror("socket error");
return -1;
}
//设置多播地址
struct sockaddr_in min;
min.sin_family = AF_INET;//通信🐟
min.sin_port = htons(9999);//端口
min.sin_addr.s_addr = inet_addr("224.6.6.6");//地址
char wbuf[128] = "";
while(1)
{
printf("请输入>>>>>");
fgets(wbuf,sizeof(wbuf),stdin);
wbuf[strlen(wbuf)-1]=0;
sendto(sfd,wbuf,strlen(wbuf),0,(struct sockaddr*)&min,sizeof(min));
printf("发送成功\n");
}
//关闭socket
close(sfd);
return 0;
}
组播的接收端流程 ------> 类似于UDP的服务器端流程
1、socket(); //创建用于通信的套接字文件描述符
2、bind(); //必须进行,但是,绑定的组播地址和端口号
3、setsockopt(); //加入多播组
4、sendto(); //向广播地址发送消息
5、close(); //关闭套接字
#include<myhead.h>
int main(int argc, const char *argv[])
{
//1、socket(); //创建用于通信的套接字文件描述符
int rfd = socket(AF_INET, SOCK_DGRAM, 0);
if(rfd == -1)
{
perror("socket error");
return -1;
}
//3、setsockopt(); //加入多播组
//准备要设置的数据
struct ip_mreqn imr;
imr.imr_multiaddr.s_addr = inet_addr("224.1.2.3"); //组播ip
imr.imr_address.s_addr = inet_addr("192.168.0.143"); //主机ip
imr.imr_ifindex = 2; //网卡编号
if(setsockopt(rfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) == -1)
{
perror("setsockopt error");
return -1;
}
printf("加入多播组成功\n");
//2、bind(); //必须进行,但是,绑定的组播地址和端口号
struct sockaddr_in rin;
rin.sin_family = AF_INET;
rin.sin_port = htons(9999);
rin.sin_addr.s_addr = inet_addr("224.1.2.3"); //组播地址
if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//4、recv(); //从组播地址中接受消息
char rbuf[128] = "";
while(1)
{
//清空容器
bzero(rbuf, sizeof(rbuf));
//接受广播消息
recv(rfd, rbuf, sizeof(rbuf), 0);
printf("收到组播消息为:%s\n", rbuf);
}
//5、close(); //关闭套接字
close(rfd);
return 0;
}