组播编程

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;

}

         

    

猜你喜欢

转载自blog.csdn.net/weixin_42039602/article/details/83867279
今日推荐