文章目录
多播
数据的收发仅仅在同一分组中进行
1 多播的特点:
1、多播地址标示一组接口
2、多播可以用于广域网使用
3、在IPv4中,多播是可选的
2 多播地址
IPv4的D类IP地址是多播地址
十进制:224.0.0.1 ~ 239.255.255.254(里面任意一个都是多播地址)
十六进制:E0.00.00.01 ~ EF.FF.FF.FE
多播地址向以太网MAC地址的映射(MAC地址不能直接全部设为FF,需要进行过滤)
3 多播的工作流程
只能将自己主机的IP加入多播组
基于mac地址不完备硬件过滤
基于IP地址的完备软件过滤
4 加入或退出多播组
多播套接口选项
int setsockopt(int sockfd, int level,int optname,
const void *optval, socklen_t optlen);
/*
sockfd:加入或退出的套接字
level: SOL_SOCKET:广播属性
IPPROTO_IP:组播属性
optname:IP_ADD_MEMBERSHIP: 加入组播
IP_DROP_MEMBERSHIP:退出组播
optval:ip_mreq结构体
optlen:ip_mreq结构体长度-
成功返回0,否则返回-1
*/
ip_mreq{} 多播地址结构体
在IPv4因特网域(AF_INET)中,多播地址结构体用如下结构体ip_mreq表示:
struct in_addr
{
in_addr_t s_addr;
}
struct ip_mreq
{
struct in_addr imr_multiaddr; //多播组IP
struct in_addr imr_interface; //将要添加到多播组的IP
/*将imr_interface添加到imr_multiaddr中*/
};
5 多播流程代码
5.1 多播发送端
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char const *argv[])
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);//创建套接字
if(sockfd<0)
{
perror("sockfd");
return -1;
}
struct sockaddr_in server,client; //创建结构体存储发送端,接收端的信息
server.sin_family=AF_INET;
server.sin_port=htons(8000);
server.sin_addr.s_addr=inet_addr(224.0.0.1);
int n=sizeof(server);
char buf[64]={0}; //缓冲区
int m=sizeof(client);
while(1)
{
fgets(buf,sizeof(buf),stdin); //从终端输入
buf[strlen(buf)-1]='\0'; //处理输入的回车
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&server,m);//发送数据
memset(buf,0,sizeof(buf));//清空缓冲区
}
close(sockfd);
return 0;
5.2 多播接收端
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char const *argv[])
{
//创建一个udp套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
perror("sockfd");
return -1;
}
//bind绑定固定的IP端口
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8000);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));
//将sockfd加入多播组224.0.0.1
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.1"); //多播组IP
mreq.imr_interface.s_addr = hton1(INADDR_ANY); //主机所有IP
setsockopt(sockfd, IPPORT_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
//测试接收多播组的消息
while(1)
{
unsigned char buf[1500] = "";
recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
printf("buf = %s \n",buf);
}
close(sockfd);
return 0;
}
客服端