c++ udp组播总结

概念

多播,也称为“组播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

特点

  • 优点
    • 具有同种业务的主机加入同一数据流,共享同一通道,节省了带宽;
    • 服务器的总带宽不受客户端带宽的限制,服务器端的带宽是常量,与客户端的数量无关;
    • 允许在广域网传输;
  • 缺点
    • 没有纠错机制;
    • 需要路由器和网络协议栈的支持;

流程

  • 发送端

    • 创建socket;
    // 第二个参数是 SOCK_DGRAM, 第三个参数0表示使用报式协议中的udp
    int socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    if(-1 == socketFd)
    {printf("create udp socket failed\n");return -1;
    }
    
    • bind(可选)
    // 使用场景: 使用同一个socketFD接收消息(即recvfrom)
    // 说明: 一般将addr.sin_addr.s_addr设置为本机网卡地址
    struct sockaddr_in cliaddr;
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(18001);
    cliaddr.sin_addr.s_addr = INADDR_ANY;  // ???本地ip
    int ret = bind(socketFd, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
    if(ret == -1)
    {printf("udp bind failed\n");return -1;
    }
    
    • 加入组播
    // 加入到组播
    struct ip_mreqn opt;
    opt.imr_address.s_addr = htonl(INADDR_ANY);
    inet_pton(AF_INET, "224.0.2.23", &opt.imr_multiaddr.s_addr);
    setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));
    

    扩展:

    1)多播使用的是D类ip地址,即224.0.0.0至239.255.255.255之间的ip地址,并被划分为局部多播地址、预留多播地址和管理权限多播地址3类;

    1) 局部多播地址: 在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。
    2) 预留多播地址: 在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
    3) 管理权限多播地址: 在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。
    

    2)组播的选项值:

    **getsockopt()/setsockopt()**的选项含义
    IP_MULTICAST_TTL设置多播组数据的TTL值
    IP_ADD_MEMBERSHIP在指定接口上加入组播组
    IP_DROP_MEMBERSHIP退出多播组
    IP_MULTICAST_IF获取默认接口或设置接口
    IP_MULTICAST_LOOP禁止组播数据回送
    • 发送数据
    char buf[128] = {0,};
    snprintf(buf, sizeof(buf), "Get cpu state,i am %d", sessionKey);
    // 发送数据
    sendto(socketFd, buf, strlen(buf)+1, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
    
    • 接收数据(如果设置了bind可直接通过socketFd接收数据)
    char buf[128] = {0,};
    struct sockaddr_in sinAddr;
    socklen_t addrlen = sizeof(sinAddr);
    recvfrom(socketFd, buf, sizeof(buf), 0, (struct sockaddr*)&sinAddr, &addrlen);
    
  • 接收端

    • 创建socket
    int socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    if(-1 == socketFd)
    {printf("create udp socket failed\n");return -1;
    }
    
    • bind(必须)
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(18000);
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    int ret = bind(fd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    if(-1 == ret)
    {printf("udp bind failed\n");return -1;
    }
    
    • 加入组播
    struct ip_mreqn opt;
    opt.imr_address.s_addr = htonl(INADDR_ANY);
    inet_pton(AF_INET, "224.0.2.23", &opt.imr_multiaddr.s_addr);setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));
    
    • 接收数据
    char buf[128] = {0,};
    struct sockaddr_in sinAddr;
    socklen_t addrlen = sizeof(sinAddr);
    recvfrom(socketFd, buf, sizeof(buf), 0, (struct sockaddr*)&sinAddr, &addrlen);
    
    • 发送数据
    char buf[128] = {0,};
    snprintf(buf, sizeof(buf), "Send cpu state,i am %d", sessionKey);
    // 发送数据
    sendto(socketFd, buf, strlen(buf)+1, 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    

示例

  • 接收端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>#define TIMEOUT 0xFFFFFFFF int main()
{// 1. create socketint socketFd = socket(AF_INET, SOCK_DGRAM, 0);if(-1 == socketFd){printf("create udp socket failed\n");return -1;}// 2. bindstruct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(18000);serveraddr.sin_addr.s_addr = INADDR_ANY;int ret = bind(socketFd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));if(-1 == ret){printf("udp bind failed\n");return -1;}// 3. set param// 3.1 ttlint ttl = 64;setsockopt(socketFd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));// 3.2 timeoutunsigned int timeout = 2000;struct timeval tm;if(TIMEOUT == timeout){tm.tv_sec = 0x7FFFFFFF;tm.tv_usec = 0;}else{tm.tv_sec = (timeout&0x7FFFFFFF) / 1000;tm.tv_usec = (timeout&0x7FFFFFFF) % 1000 * 1000;}setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tm, sizeof(tm));// 4. join multi struct ip_mreqn opt;opt.imr_address.s_addr = INADDR_ANY; // 本地地址inet_pton(AF_INET, "224.0.2.23", &opt.imr_multiaddr.s_addr);setsockopt(socketFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));// 5. recvfrom and sendtowhile(1){char recv_buf[128] = {0,};int recvlen = recvfrom(socketFd, recv_buf, sizeof(recv_buf), 0, NULL, NULL);if(recvlen < 0){//printf("server not recv msg,wait...\n");continue;}printf("server recv msg:%s\n", recv_buf);sleep(4);
/*char send_buf[128] = {0,};snprintf(send_buf, sizeof(send_buf), "Send cpu state,i am %d", 1);sendto(socketFd, send_buf, sizeof(send_buf), 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr));printf("server send msg:%s\n", send_buf);
*/}return 0;
}

接收端程序运行时打印:

[root@localhost debug.x64-linux-g8]# ./testUdpServer
server recv msg:Send cpu state,i am 1
server recv msg:Send cpu state,i am 1
server recv msg:Send cpu state,i am 1
server recv msg:Send cpu state,i am 1
server recv msg:Send cpu state,i am 1
server recv msg:Send cpu state,i am 1
  • 发送端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>#define TIMEOUT 0xFFFFFFFF int main()
{// 1. create socketint socketFd = socket(AF_INET, SOCK_DGRAM, 0);if(-1 == socketFd){printf("create udp socket failed\n");return -1;}// 2. bind
/*struct sockaddr_in clientaddr;clientaddr.sin_family = AF_INET;clientaddr.sin_port = htons(18001);clientaddr.sin_addr.s_addr = INADDR_ANY;int ret = bind(socketFd, (struct sockaddr*)&clientaddr, sizeof(clientaddr));if(-1 == ret){printf("udp bind failed\n");return -1;}
*/// 3. set param// 3.1 ttlint ttl = 64;setsockopt(socketFd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));// 3.2 timeoutunsigned int timeout = 2000;struct timeval tm;if(TIMEOUT == timeout){tm.tv_sec = 0x7FFFFFFF;tm.tv_usec = 0;}else{tm.tv_sec = (timeout&0x7FFFFFFF) / 1000;tm.tv_usec = (timeout&0x7FFFFFFF) % 1000 * 1000;}setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tm, sizeof(tm));// 4. set IP_MULTICAST_IFstruct in_addr opt;inet_pton(AF_INET, "224.0.2.23", &opt.s_addr);setsockopt(socketFd, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));struct sockaddr_in clientaddr;clientaddr.sin_family = AF_INET;clientaddr.sin_port = htons(18000); inet_pton(AF_INET, "224.0.2.23", &clientaddr.sin_addr.s_addr);// 5. recvfrom and sendtowhile(1){char send_buf[128] = {0,};snprintf(send_buf, sizeof(send_buf), "Send cpu state,i am %d", 1);sendto(socketFd, send_buf, sizeof(send_buf), 0, (struct sockaddr*)&clientaddr, sizeof(clientaddr));printf("client send msg:%s\n", send_buf);sleep(2);
/*char recv_buf[128] = {0,};struct sockaddr_in sinAddr;socklen_t addrlen = sizeof(sinAddr);int recvlen = recvfrom(socketFd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&sinAddr, &addrlen);if(recvlen < 0){printf("client not recv msg,wait...\n");continue;}printf("client recv msg:%s\n", recv_buf);
*/}return 0;
}

发送端程序运行时打印:

[root@localhost debug.x64-linux-g8]# ./testUdpClient
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1
client send msg:Send cpu state,i am 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/18937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【A200】Ubuntu18.04 + ROS-Melodic + 比业电子VISIOSCAN雷达 评测

大家好&#xff0c;我是虎哥&#xff0c;朋友介绍&#xff0c;有一款单线激光雷达&#xff0c;25米的检测距离&#xff0c;有80HZ的扫描频率&#xff0c;而且角度分辨率最高可以到0.1&#xff0c;这个参数我确实没有见过&#xff0c;所以立刻着手从厂家那申请到了VISIOSCAN雷达…

Flask框架-流量控制:flask-limiter的使用

一、flask使用flask-limiter存在版本问题 Flask1.1.4 Flask-Bootstrap3.3.7.1 Flask-Caching1.9.0 Flask-Cors3.0.10 Flask-Limiter1.4 Flask-Migrate2.5.3 Flask-RESTful0.3.8 Flask-Script2.0.6 Flask-SocketIO5.0.1 Flask-Sockets0.2.1 Flask-SQLAlchemy2.4.4 Jinjia22.11.…

JVM基础篇-虚拟机栈

JVM基础篇-虚拟机栈 定义 Java Virtual Machine Stacks &#xff08;Java 虚拟机栈&#xff09; 每个线程运行时所需要的内存&#xff0c;称为虚拟机栈每个栈由多个栈帧&#xff08;Frame&#xff09;组成&#xff0c;对应着每次方法调用时所占用的内存每个线程只能有一个活动…

机房断网断电监测网关支持远程告警

RTU5028E网络故障监测终端是一款功能强大且方便实用的设备&#xff0c;集合了断网、断电、网线故障报警功能。它支持同时监测多达7台网络设备&#xff0c;可以帮助用户快速定位远程网络设备离线的原因。此外&#xff0c;它还具备自动重启和远程重启网络设备的功能&#xff0c;为…

思科模拟器配置静态路由(下一跳使用IP)

Router0配置代码&#xff1a;##端口配置 Router(config)#int fastEthernet 0/0 Router(config-if)#ip address 192.168.10.254 255.255.255.0 Router(config-if)#no shutdown Router(config-if)#int fastEthernet 0/1 Router(config-if)#ip address 192.168.20.1 255.255.255.2…

stm32串口通信,收发字符串,并对其进行解析

串口以字符串接收和发送 将传输的数据转化为整数&#xff08;正负&#xff09; stm32发送端 motor_position Read_Encoder_Angle(Encoder);sensor_position Get_Adc_Average_Angle(Adc);motor_velocity Read_Encoder_Speed(Encoder);sensor_velocity Get_Adc_Average_Spe…

深度剖析数据在内存中的存储

目录 数据类型介绍 类型的基本归类 整形家族: 浮点数家族: 构造类型: 指针类型 空类型: 整形在内存中的存储 原码、反码、补码 大小端介绍 什么大端小端: 为什么有大端和小端: 练习 浮点型在内存中的储存 一个例子 浮点数存储规则 数据类型介绍 前面我们…

SpringBoot实现多数据源,集成mybatis和JPA

前言&#xff1a; 使用2个数据库&#xff0c;数据库A&#xff1a;phm 数据库B&#xff1a;mcs 。 在项目中主要使用hibernate实现全自动ORM,但是在复杂的业务中&#xff0c;需要使用mybatis来实现业务需求。 一、入门 1、添加依赖 <!-- 整合mybatis --><dependen…

Windows同时安装两个版本的JDK并随时切换,以JDK6和JDK8为例,并解决相关存在的问题(亲测有效)

Windows同时安装两个版本的JDK并随时切换&#xff0c;以JDK6和JDK8为例&#xff0c;并解决相关存在的问题&#xff08;亲测有效&#xff09; 1.下载不同版本JDK 这里给出JDK6和JDK的百度网盘地址&#xff0c;具体安装过程&#xff0c;傻瓜式安装即可。 链接&#xff1a;http…

【Linux】用户相关内容

如果命令ll 出现以上信息&#xff0c;UID为具体的数字&#xff0c;代表之前UID为502的用户被删除了。 更改目录或文件所属用户和所属组 在Linux中&#xff0c;创建一个文件时&#xff0c;该文件的拥有者都是创建该文件的用户。 更改所属用户 chown 用户名 文件名/目录名 更…

VisualStudioWindows下 远程调试

前置条件 1、调试方与被调试方&#xff0c;以下简称调试方为A&#xff0c;被调试方为B。A与B双方能相互ping通 2、B需要运行RemoteDebugger服务&#xff0c;该程序位于C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Remote Debugger下。 我这里是安装…

基于总线加锁和缓存锁(CPU实现原子操作的两种方式)

总线锁 总线锁就是使用处理器提供的一个 LOCK&#xff03;信号&#xff0c;当一个处理器在总线上输出此信号时&#xff0c;其他处理器的请求将被阻塞住&#xff0c;那么该处理器可以独占共享内存。 CPU和内存之间的通信被锁&#xff01;&#xff01; 如果多个 处 理器同 时对 …

windows下的txt文档,传到ubuntu后,每行后面出现^M,怎么处理?

问题背景&#xff1a;windows下pycharm生成的txt文档&#xff0c;传到ubuntu后&#xff0c;每行后面出现^M 用vim打开显示 使用cat -A filename显示如下 参考https://www.lmlphp.com/user/16697/article/item/579325/给出的几种方法 方法一、dos2unix filename。服务器没装…

配置IPv6 over IPv4手动隧道示例

组网需求 如图1所示&#xff0c;两台IPv6主机分别通过SwitchA和SwitchC与IPv4骨干网络连接&#xff0c;客户希望两台IPv6主机能通过IPv4骨干网互通。 图1 配置IPv6 over IPv4手动隧道组网图 配置思路 配置IPv6 over IPv4手动隧道的思路如下&#xff1a; 配置IPv4网络。配置接…

iptables防火墙、filter表控制、扩展匹配、使用iptables配置网络型防火墙、NAT原理、配置SNAT

day05 day05iptables防火墙filter表filter中的三条链环境准备iptables操作验证FORWARD链准备环境配置FORWARD链NAT配置SNAT iptables iptables有多种功能&#xff0c;每一种功能都用一张表来实现最常用的功能是防火墙和NAT从RHEL7开始&#xff0c;默认的防火墙为firewalld&a…

fiddler 手机抓包(含https) 完整流程

第一部分&#xff1a;下载并安装fiddler 一.使用任一浏览器搜索【fiddler下载安装】&#xff0c;并下载fiddler 安装包。 二.fiddler安装包下载成功后&#xff0c;将下载的fiddler压缩包解压到自定义文件夹【fiddler】或者解压到当前文件夹下&#xff0c;双击文件夹中的【fidd…

一起学算法(链表篇)

1.链表的概念 对于顺序存储的结构最大的缺点就是插入和排序的时候需要移动大量的元素&#xff0c;所以链表的出生由此而来 先上代码&#xff1a; // 链表 public class LinkedList<T extends Comparable> {// 结点类class Node {T ele; // 当前结点上的元素内容Node ne…

台式机/工控机通过网线共享笔记本电脑无线网络linux系统下 usb网卡的驱动安装

一、台式机/工控机通过网线共享笔记本电脑无线网络 1、 将台式机通过网线和笔记本连接。 2、 将笔记本的“本地连接”和“无线网络连接”的ipv4均设置为自动获取。 4.修改台式机的IP地址为如下&#xff08;对应笔记本信息&#xff09; IP地址为192.168.XXX.12 子网掩码为255.2…

flask

flask 介绍 # python 界的web框架 -Django&#xff1a;大而全&#xff0c;快速开发&#xff0c;公司内部项目 -Flask&#xff1a;小而精&#xff0c;不具备web开发好多功能&#xff0c;丰富的第三方插件 -FastApi&#xff1a;异步框架&#xff0c;主要为了做前后端…

接口/Web自动化测试如何做?框架如何搭建封装?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试怎么做…