Ubuntu环境下Udp组播Demo实例

前言

组播又称多目标广播、多播。网络中使用的一种传输方式,它允许把 所发消息传送给所有可能目的地中的一个经过选择的子集,即向明确指出的多种地址输送信息。是一种在一个发送者和多个接收者之间进行通信的方法。与任播(anycast)和单播(unicast)一起,组播也是一种IPv6的包传送方式。


一、组播IP简介?

IP地址
组播IP地址用于标识一个IP组播组。IANA(internet assigned number authority)把D类地址空间分配给IP组播,其范围是从224.0.0.0到239.255.255.255。如二进制表示,IP组播地址前四位均为1110八位组⑴ 八位组⑵ 八位组⑶ 八位组⑷1110
XXXX XXXXXXXX XXXXXXXX XXXXXXXX组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。

二、组播源码

1.组播发送端

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 

int main(int argc, char *argv[])
{
    //建立套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);           //IPV4,数据报套接字类型,不指定协议
 
    //声明将连接地址
        struct sockaddr_in  srvaddr,srvaddr_loacl;
    
   	srvaddr_loacl.sin_family = AF_INET,                              //协议类型IPV4
	srvaddr_loacl.sin_port = htons(44444),                            //端口号-网络字节序
	srvaddr_loacl.sin_addr.s_addr = inet_addr("224.2.2.2");                 //IP地址-字符串转IP
    bind(sock_fd,(const struct sockaddr*)&srvaddr_loacl,sizeof(srvaddr_loacl));
    
	srvaddr.sin_family = AF_INET,                              //协议类型IPV4
	srvaddr.sin_port = htons(55555),                            //端口号-网络字节序
	srvaddr.sin_addr.s_addr = inet_addr("224.2.2.2");                 //IP地址-字符串转IP
 
	
	struct ip_mreq	ipMreq;
	setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_IF, (void*)&srvaddr,
		sizeof(struct sockaddr_in));
	ipMreq.imr_interface.s_addr = inet_addr("192.168.13.80");
	ipMreq.imr_multiaddr.s_addr = inet_addr("224.2.2.2");
	//setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipMreq, sizeof(ipMreq)); 
 
    //发送数据
    char buf[88] = { 0 };
	int count = 0;
    while (1)
    {
        memset(buf,0, 88);
        sprintf(buf, "%d",count);
		printf("udp client send:%s\n",buf);
        sendto(sock_fd, buf, strlen(buf), 0, (const struct sockaddr*)&srvaddr, sizeof(srvaddr));
		count++;
		sleep(1);
    }
 
    //关闭套接字
    close(sock_fd);
 
    return 0;
}

在Ubuntu环境下使用Gcc编译

gcc xxx.c -o xxx.exe

2.接收端源码

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define BUF_SIZE 		88
#define PORT     		55555            //端口号
#define ADDR     		"192.168.13.80"  //设置本地IP地址
#define MUNICASTADDR    "224.2.2.2"            //组播IP
 
int main(int argc, char *argv[])
{
    //建立套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);           //IPV4,数据报套接字类型,不指定协议
 
    //说明本服务器地址
    struct sockaddr_in srvaddr;
	srvaddr.sin_family = AF_INET,                              //协议类型IPV4
	srvaddr.sin_port = htons(PORT),                            //端口号-网络字节序
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);                //IP地址-任意地址
 
        //绑定地址
        bind(sock_fd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));
	
	//srvaddr.sin_addr.s_addr = inet_addr(ADDR);
	setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_IF, (void*)&srvaddr,sizeof(struct sockaddr_in));
 
	struct ip_mreq	ipMreq;
	ipMreq.imr_interface.s_addr = inet_addr(ADDR);     // 使本地IP地址加入组播
	ipMreq.imr_multiaddr.s_addr = inet_addr(MUNICASTADDR);  //使组播IP加入组播
       setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipMreq, sizeof(ipMreq));/*组播接收端一定要设置*/
    //接收数据
    char buf[BUF_SIZE] = { 0 };
    struct sockaddr_in cliaddr;
    socklen_t cliaddrlen = sizeof(cliaddr);
    memset(&cliaddr,0,sizeof(cliaddr));   //清零初始化
 
    
    while (1)
    {
        bzero(buf, BUF_SIZE);      //清零初始化
        bzero(&cliaddr, cliaddrlen);  //清零初始化
        recvfrom(sock_fd, buf, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &cliaddrlen);
        printf("udp server from [%s - %hu]:%s\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port,buf);
    }
 
    //关闭套接字
    close(sock_fd);
 
    return 0;
}

总结

bind函数解析

#include<sys/socket.h>

int bind(int sockfd,const struct sockaddr*&, socklen_t addrlen);

第一个参数作用:bind函数把一个本地协议地址赋予一个套接字。
第二个参数作用:是一个指向特定协议的地址结构的指针。
第三个参数作用:地址结构的长度。

ipMreq函数解析

	struct ip_mreq	ipMreq;
	ipMreq.imr_interface.s_addr = inet_addr(ADDR);     // 使本地IP地址加入组播
	ipMreq.imr_multiaddr.s_addr = inet_addr(MUNICASTADDR);  //使组播IP加入组播
 

作用:声明一个ip_mreq的结构体变量,用于加入组播。

setsockopt函数解析

 setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipMreq, sizeof(ipMreq));/*组播一定要写接收*/

第一个参数作用:把本地设置赋值给套接字(sock_fd)。
第二个参数作用:引入协议包(IPPROTO_IP)。
第三个参数作用:加入一个组播。
第四个参数作用:指向设置设置组播的结构体。
第五个参数作用:地址结构的长度。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东.'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值