使用UDP实现组播-使用 setsockopt 设置接收端加入多播组-传输层

目录

  • 使用UDP实现组播
    • 概念
    • 组播流程
    • 使用 setsockopt 设置加入多播组
    • 代码实现
      • 接收端---01receive.c
      • 发送端---02send.c
    • 代码实现
    • 注意
  • 6.非原创

使用UDP实现组播

使用UDP实现组播-使用 setsockopt 设置接收端加入多播组-传输层_第1张图片

概念

组播 又称为 多播,只有加入某个多播组的主机才能收到数据。

组播的地址

  • D类地址
    不分网络地址和主机地址,第1字节的前4位固定为1110(224.0.0.1 – 239.255.255.255)
    224D <==>1110 0000B
    使用UDP实现组播-使用 setsockopt 设置接收端加入多播组-传输层_第2张图片

  • D类ip地址,每一个都可以代表一个多播组。

组播流程

发送者:
		1.创建套接字 socket( )
		2.填充组播信息结构体 sockaddr_in
		3.发送数据 sendto( )
-------
接收者:|
-------
		1.创建套接字 scoket( )
		2.填充组播信息结构体 sockaddr_in
		3.将套接字与组播信息结构体绑定 bind( )
		------------------------------------
		4.设置为加入多播组 setsockopt( )
		------------------------------------
		5.接收数据 recvfrom( )

使用 setsockopt 设置加入多播组

#include           
#include 

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

参数:
	sockfd:套接字
	
	level:选项的级别
		   IPPROTO_IP	IP级别
		
	optname:选项的名称
			 IP_ADD_MEMBERSHIP	在指定接口上加入组播组
  
  	optval:结构体
    		struct ip_mreqn {
        		struct in_addr imr_multiaddr; /* 多播组的地址 */
        		struct in_addr imr_address;   /* 本地的IP地址 */
        		int    imr_ifindex;  		 /* 接口索引 0 表示任意接口 */
    		};

	optlen:optval的大小

setsockopt 其他用法

  • 使用setsockopt设置超时检测多线程实现TCP并发服务器使用setsockopt设置超时检测
  • 使用setsockopt设置端口复用多线程实现TCP并发服务器使用setsockopt设置超时检测-使用setsockopt设置端口复用

代码实现

接收端—01receive.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERRLOG(errmsg)                                       \
	do                                                       \
	{                                                        \
		printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
		perror(errmsg);                                      \
		exit(-1);                                            \
	} while (0)

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[]);

int main(int argc, const char *argv[])
{
	//检测命令行参数个数
	if (3 != argc)
	{
		printf("Usage : %s  \n", argv[0]);
		exit(-1);
	}

	//创建套接字-填充服务器网络信息结构体-绑定
	int sockfd = socket_bind(argv);

	//用来保存发送端信息的结构体
	// UPD网络通信 如果需要给发送端回信,就必须保存发送端的网络信息结构体
	struct sockaddr_in client_addr;
	memset(&client_addr, 0, sizeof(client_addr));
	socklen_t client_addr_len = sizeof(client_addr);

	/*-------------------------------------------------------------------------------------------------*/
	//设置加入多播组
	struct ip_mreqn mreq;
	mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);	  //多播组ip地址
	mreq.imr_address.s_addr = inet_addr("192.168.250.100"); //本地ip地址
	mreq.imr_ifindex = 0; 							  // 接口索引 0 表示任意接口 

	//                   /套接字  /IP级别     /在指定接口上加入组播组
	if (-1 == setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreqn)))
		ERRLOG("setsockopt error");

	/*-------------------------------------------------------------------------------------------------*/

	char buff[128] = {0};

	while (1)
	{
		//阻塞接收发送端发来的数据
		if (-1 == recvfrom(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&client_addr, &client_addr_len))
			ERRLOG("recvfrom error");

		printf("客户端 (%s:%d) 发来数据:[%s]\n",
			   inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buff);
	}
	//关闭监听套接字  一般不关闭
	close(sockfd);

	return 0;
}

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[])
{
	// 1.创建套接字      //IPV4   //UDP
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == sockfd)
		ERRLOG("socket error");

	// 2.填充广播信息结构体
	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	//端口号  填 8888 9999 6789 ...都可以
	server_addr.sin_port = htons(atoi(argv[2]));
	// ip地址 组播的IP地址  224.0.0.1 – 239.255.255.255
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);

	//结构体长度
	socklen_t server_addr_len = sizeof(server_addr);

	// 3.将套接字和组播信息结构体绑定
	if (-1 == bind(sockfd, (struct sockaddr *)&server_addr, server_addr_len))
		ERRLOG("bind error");

	return sockfd;
}

发送端—02send.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERRLOG(errmsg)                                       \
    do                                                       \
    {                                                        \
        printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
        perror(errmsg);                                      \
        exit(-1);                                            \
    } while (0)

int main(int argc, const char *argv[])
{
    //检测命令行参数个数
    if (3 != argc)
    {
        printf("Usage : %s  \n", argv[0]);
        exit(-1);
    }

    // 1.创建套接字      //IPV4   //UDP
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sockfd)
        ERRLOG("socket error");

    // 2.填充组播信息结构体
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr)); // 清空
    server_addr.sin_family = AF_INET;             // IPV4
    //端口号  填 8888 9999 6789 ...都可以
    // atoi字符串转换成整型数
    // htons将无符号2字节整型  主机-->网络
    server_addr.sin_port = htons(atoi(argv[2]));

    // ip地址 是组播的ip地址 224.0.0.1 – 239.255.255.255
    // inet_addr字符串转换成32位的网络字节序二进制值
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);

    //结构体长度
    socklen_t server_addr_len = sizeof(server_addr);

    char buff[128] = {0};

    while (1)
    {
        printf("请输入 : ");
        scanf("%s", buff);
        if (0 == strcmp(buff, "quit"))
            break;

        //将数据以组播的形式发送----发送到组播的ip地址
        if (-1 == sendto(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, server_addr_len))
            ERRLOG("sendto error");
        
    }
    //关闭监听套接字  一般不关闭
    close(sockfd);

    return 0;
}

代码实现

使用UDP实现组播-使用 setsockopt 设置接收端加入多播组-传输层_第3张图片

注意

接收端 使用 setsockopt 设置加入多播组

应该插放bind套接字网络信息结构体绑定 之后,recvfrom接收发送端数据之前

设置加入多播组
	struct ip_mreqn mreq;
	mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);	  //多播组ip地址
	mreq.imr_address.s_addr = inet_addr("192.168.250.100"); //本地ip地址
	mreq.imr_ifindex = 0; 							  // 接口索引 0 表示任意接口 

	                     /套接字  /IP级别     /在指定接口上加入组播组
	if (-1 == setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreqn)))
		ERRLOG("setsockopt error");

6.非原创

你可能感兴趣的:(Linux&C,udp,网络,服务器)