1、组播IP地址范围:224.0.0.0 ~ 239.255.255.255
组播以太网地址(MAC地址):开头高三个字节是01:00:5e
2、组播分为两部分:
组播数据流:目的
组播控制流:(IGMP)分三种报文:report(join),leave,query
3、组播编程
client:1、IP_MULTICAST_LOOP
2、IP_ADD_MEMBERSHIP
3、IP_DROP_MEMBERSHIP
netinet/in.h
/* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
#ifdef __USE_MISC
/* IPv4 multicast request. */
struct ip_mreq
{
/* IP multicast address of group. */
struct in_addr imr_multiaddr;
/* Local IP address of interface. */
struct in_addr imr_interface;
};
内容:组播客户端
要求:接收组播发布的消息,接收5次自动退出;
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#define MULTICAST_IP "224.255.255.255"
#define PORT 6667
int main(int argc,char *argv[])
{
int sockfd;
int i;
int addrlen,recvbytes,localen;
int opterr1,opterr2,opterr3,binderr;
int loopopt = 1;
int opt = 1;
char recvbuf[128];
struct sockaddr_in local ;
struct ip_mreq mcast_addr;
addrlen = sizeof(struct ip_mreq);
localen = sizeof(local);
sockfd =socket(AF_INET,SOCK_DGRAM,0);//建立socket
if(sockfd ==-1)
{
printf("creat socket error,errno:%d\n",errno);
return -1;
}
//套接字设为可重用
opterr1 = setsockopt(sockfd ,SOL_SOCKET ,SO_REUSEADDR, &opt,sizeof(opt));
if(opterr1< 0 )
{
perror("setsockopt1 error:\n");
}
//禁止组播数据回送
opterr2 = setsockopt(sockfd ,IPPROTO_IP ,IP_MULTICAST_LOOP,
&loopopt,sizeof(loopopt));
if(opterr2< 0 )
{
perror("setsockopt2 error:\n");
}
bzero(&local ,sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(PORT);
bzero(&mcast_addr,addrlen);
mcast_addr.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
mcast_addr.imr_interface.s_addr = htonl(INADDR_ANY);
//将套接字与本地地址绑定
binderr = bind(sockfd,(struct sockaddr *)&local ,localen);
if(binderr < 0)
{
perror("Bind err:\n");
close(sockfd);
}
//加入组播组
opterr3 = setsockopt(sockfd ,IPPROTO_IP ,IP_ADD_MEMBERSHIP,
&mcast_addr, addrlen);
if(opterr3 < 0 )
{
perror("setsockopt3 error:\n");
}
//5次循环读取组播客户端发来的数据
for(i =0 ;i < 5 ;i++)
{
bzero(recvbuf, 128 );
recvbytes = recvfrom(sockfd,recvbuf,sizeof(recvbuf),0,(struct sockaddr*)(&local),&localen);
if(recvbytes< 0)
{
perror("recv msg error.\n");
}
printf("%d time recv msg:%s\n",i,recvbuf);
sleep(1);
}
//读取完毕,退出组播组,结束
setsockopt(sockfd ,IPPROTO_IP ,IP_DROP_MEMBERSHIP,
&mcast_addr, addrlen);
close(sockfd);
return 0;
}
内容:编写以组播服务器
要求:定期发送一组数据给加入组播组的所有客户端
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#define PORT 6667
#define MULTICAST_IP "224.255.255.255"
int main(int argc,char *argv[])
{
int sockfd;
int mcastlen,sendbytes;
int opterr;
int opt = 1;
char sendbuf[128] = "Hello,I am multicast server!welcom to join me!";
struct sockaddr_in mcast_addr;
//建立socket
mcastlen = sizeof(mcast_addr);
sockfd =socket(AF_INET,SOCK_DGRAM,0);
if(sockfd ==-1)
{
printf("creat socket error,errno:%d\n",errno);
return -1;
}
opterr = setsockopt(sockfd ,SOL_SOCKET ,SO_REUSEADDR, &opt,sizeof(opt));
if(opterr< 0 )
{
perror("setsockopt error:\n");
}
bzero(&mcast_addr,mcastlen);
mcast_addr.sin_family = AF_INET;
mcast_addr.sin_port = htons(PORT);
mcast_addr.sin_addr.s_addr = inet_addr(MULTICAST_IP);
while(1)
{
sendbytes = sendto(sockfd,sendbuf,strlen(sendbuf),0,(struct sockaddr*)(&mcast_addr),mcastlen);
if(sendbytes<0)
{
perror("send msg error.\n");
}
printf("send msg success!\n");
sleep(1);
}
return 0;
}