- 组播:
过多的广播
会占用网络带宽
,产生广播风暴
的现象,从而影响正常的通信
活动;
组播
(或者多播
)是局域网内部
的通信,只有加入到某个多播组
的主机才能收到数据;
- 组播的方式既可以发给多个主机,又能避免广播带来过多的网络负载;
- 组播地址 :D类地址:"
224.0.0.1~239.255.255.254
";
- 设置组播的流程:
- 发送方(UDP的客户端):
- 一、创建用户数据报套接字(socket函数):
c
复制代码
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd)
{
perror("socket error");
exit(-1);
}
- 二、填充组播信息结构体( struct sockaddr_in):
c
复制代码
struct sockaddr_in serveraddr;
socklen_t serveraddr_len = sizeof(serveraddr);
memset(&serveraddr,0,serveraddr_len);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(M_IP);
serveraddr.sin_port = htons(PORT);
c
复制代码
char buf[128] = {0};
while(true)
{
memset(buf,0,sizeof(buf));
fgets(buf,128,stdin);
buf[strlen(buf)-1] = '\0';
if(!strncmp(buf,"quit",4))
{
break;
}
//给服务器发送数据
if(-1 == (sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&serveraddr,serveraddr_len)))
{
perror("sendto error");
exit(-1);
}
}
c
复制代码
close(sockfd);
- 接收方(UDP的服务器):
- 一、创建用户数据报套接字(socket函数):
c
复制代码
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd)
{
perror("socket error");
exit(-1);
}
- 二、填充组播信息结构体(struct sockaddr_in):
c
复制代码
struct sockaddr_in serveraddr,clientaddr;
socklen_t serveraddr_len = sizeof(serveraddr);
socklen_t clientaddr_len = sizeof(clientaddr);
memset(&serveraddr,0,serveraddr_len);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(M_IP);
serveraddr.sin_port = htons(PORT);
- 三、用户数据报套接字和广播信息结构体绑定(bind函数):
c
复制代码
if(-1 == (bind(sockfd,(struct sockaddr *)&serveraddr,serveraddr_len)))
{
perror("bind error");
exit(-1);
}
c
复制代码
struct ip_mreqn {
struct in_addr imr_multiaddr;
struct in_addr imr_address;
int imr_ifindex;
};
struct ip_mreqn multi_group;
multi_group.imr_address.s_addr = INADDR_ANY;
multi_group.imr_multiaddr.s_addr = inet_addr(M_IP);
multi_group.imr_ifindex = 0;
if(-1 == (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&multi_group,sizeof(multi_group))))
{
perror("setsockopt error");
exit(-1);
}
c
复制代码
char buf[128] = {0};
while(true)
{
memset(buf,0,sizeof(buf));
if(-1 == recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,&clientaddr_len))
{
perror("recvfrom error");
exit(-1);
}
printf("客户端[%s:%d]发来数据[%s]\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),buf);
}
c
复制代码
close(sockfd);