当前位置: 首页 > news >正文

C/C++ 实现UDP发送或接收组播消息,并可指定接收发送网卡

一、发送端代码

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include "UDPOperation.h"
#include "GlobalVariable.h"
#include "Logger.h"
#include "EndException.h"
#include "BaseException.h"UDPOperation::UDPOperation(char* remote_host, int remote_port, char* interface) : fd(-1)
{// 创建通信的套接字this->remote_host = remote_host;this->remote_port = remote_port;this->interface = interface;memset(&(this->cliaddr), 0, sizeof(sockaddr_in));this->cliaddr.sin_family = AF_INET;this->cliaddr.sin_port = htons(this->remote_port); // 接收端需要绑定remote_port端口
}UDPOperation::~UDPOperation() {}bool UDPOperation::create_udpsocket()
{this->fd = socket(AF_INET, SOCK_DGRAM, 0);if (this->fd == -1){LOG_ERROR("Socket creation failed: %s", strerror(errno));throw EndException(errno, strerror(errno));}inet_pton(AF_INET, this->remote_host, &this->cliaddr.sin_addr.s_addr);hostent* host = gethostbyname(remote_host);unsigned long hostip = *(unsigned long *)host->h_addr;this->cliaddr.sin_addr.s_addr = hostip;unsigned char net = hostip & 0xff;if (net > 223 && net < 240)  // 如果是多播{   char numeric_ip[32] = "\0";get_ifaddr (numeric_ip);struct in_addr outputif;outputif.s_addr = inet_addr (numeric_ip);LOG_INFO("interface = %s, numeric_ip = %s", interface, numeric_ip);if (setsockopt(this->fd, IPPROTO_IP, IP_MULTICAST_IF, (char* ) &outputif, sizeof(struct in_addr))){throw EndException(errno, strerror(errno));}}return true;
}int UDPOperation::get_ifaddr(char* addr)
{int sock = socket (AF_INET, SOCK_DGRAM, 0);struct ifreq ifr;memset (&ifr, 0, sizeof (ifr));strcpy (ifr.ifr_name, interface);if (ioctl (sock, SIOCGIFADDR, &ifr) < 0) {close (sock);throw EndException(errno, strerror(errno));return 1;}strcpy (addr, inet_ntoa(((struct sockaddr_in* ) &(ifr.ifr_addr))->sin_addr));close (sock);return 0;
}void UDPOperation::destory_udpsocket()
{close(this->fd);
}bool UDPOperation::send_buffer(char *buffer)
{socklen_t len = sizeof(struct sockaddr_in);// 数据广播int t = sendto(this->fd, buffer, SEND_UDP_PER_TSPACKET_SIZE, 0, (struct sockaddr *)&cliaddr, len);if (t == -1){LOG_ERROR("Socket send failed: %s", strerror(errno));throw BaseException(errno, strerror(errno));}return true;
}

二、接收端代码

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include "UDPOperation.h"
#include "GlobalVariable.h"
#include "Logger.h"
#include "EndException.h"
#include "BaseException.h"UDPOperation::UDPOperation(std::string remote_host, int remote_port, char* interface) : fd(-1)
{// 创建通信的套接字this->remote_host = remote_host;this->remote_port = remote_port;this->interface = interface;memset(&(this->cliaddr), 0, sizeof(sockaddr_in));this->cliaddr.sin_family = AF_INET;this->cliaddr.sin_addr.s_addr = inet_addr(this->remote_host.c_str());this->cliaddr.sin_port = htons(this->remote_port); // 接收端需要绑定remote_port端口
}UDPOperation::~UDPOperation() {}bool UDPOperation::create_udpsocket()
{this->fd = socket(AF_INET, SOCK_DGRAM, 0);if (this->fd == -1){LOG_ERROR("Socket creation failed: %s", strerror(errno));throw EndException(errno, strerror(errno));}// 设置socket选项,允许重用地址  int reuse = 1;  if (setsockopt(this->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {  LOG_ERROR("Error setting socket option: %s", strerror(errno));throw EndException(errno, strerror(errno)); }  struct sockaddr_in local_addr;      //local addressmemset(&local_addr, 0, sizeof(local_addr));local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = inet_addr("0.0.0.0");   // 设定本地监听必须是0.0.0.0 这里是关键!local_addr.sin_port = htons(remote_port);             //this port must be the group port//建立本地捆绑(主机地址/端口号)if (bind(fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) != 0){LOG_ERROR("Error binding socket: %s", strerror(errno));throw EndException(errno, strerror(errno)); }// 如果是组播 加入组播int net = stoi(remote_host.substr(0, remote_host.find('.')));if (net >= 224 && net <= 239){struct ip_mreq mreq;mreq.imr_multiaddr.s_addr = inet_addr(this->remote_host.c_str());if(strlen(interface) == 0){mreq.imr_interface.s_addr = htonl(INADDR_ANY);                //任意接口接收组播信息}else{char numeric_ip[32] = "\0";get_ifaddr (numeric_ip);LOG_INFO("interface = %s, numeric_ip = %s", interface, numeric_ip);mreq.imr_interface.s_addr = inet_addr(numeric_ip);    //指定新接口接收组播信息}if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) {LOG_ERROR("Error setting socket option for multicast: %s", strerror(errno));throw EndException(errno, strerror(errno));}}return true;
}void UDPOperation::destory_udpsocket()
{close(this->fd);
}int UDPOperation::recv_buffer(uint8_t *buffer, int size)
{socklen_t len = sizeof(struct sockaddr_in);int bytes_received = recvfrom(this->fd, buffer, size, 0, (struct sockaddr *)&this->cliaddr, &len);  if (bytes_received < 0) {  LOG_ERROR("Error receiving data: %s", strerror(errno));throw BaseException(errno, strerror(errno)); }  return bytes_received;
}int UDPOperation::get_ifaddr(char* addr)
{int sock = socket (AF_INET, SOCK_DGRAM, 0);struct ifreq ifr;memset (&ifr, 0, sizeof (ifr));strcpy (ifr.ifr_name, interface);if (ioctl (sock, SIOCGIFADDR, &ifr) < 0) {close (sock);throw EndException(errno, strerror(errno));return 1;}strcpy (addr, inet_ntoa(((struct sockaddr_in* ) &(ifr.ifr_addr))->sin_addr));close (sock);return 0;
}

三、若udp组播接收不到数据可能是如下原因

# 2. 看系统有没有过滤组播包:
# 2.1 看接受组播的网卡是否过滤了:
cat /proc/sys/net/ipv4/conf/en4/rp_filter
# 如果是0, good。
# 2.2 看all网卡是否过滤了:
cat /proc/sys/net/ipv4/conf/all/rp_filter
# 如果是0, good。
# 这两个值都必须是0,才行!如果不是0,这样修改:
# 2.3 临时修改取消过滤:
sudo sysctl -w net.ipv4.conf.en4.rp_filter=0
sudo sysctl -w net.ipv4.conf.all.rp_filter=0
# 2.4 永久修改取消过滤(重启亦有效):
sudo vi /etc/sysctl.conf
# 改为:
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0

rp_filter参数详细介绍:
rp_filter参数有三个值,0、1、2,具体含义:

0:不开启源地址校验。

1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径, 则直接丢弃该数据包。

2:开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包。

相关文章:

C/C++ 实现UDP发送或接收组播消息,并可指定接收发送网卡

一、发送端代码 #include <iostream> #include <unistd.h> #include <stdio.h> #include <string.h> #include <net/if.h> #include <netinet/in.h> #include <netdb.h> #include <sys/ioctl.h> #include "UDPOperation…...

纬创出售印度子公司给塔塔集团,结束iPhone代工业务 | 百能云芯

纬创&#xff08;Wistron&#xff09;董事会于10月27日通过决议&#xff0c;同意以1.25亿美元的价格出售其印度子公司Wistron InfoComm Manufacturing (India) Private Limited&#xff08;WMMI&#xff09;的100%股权给塔塔集团&#xff0c;交割将尽快完成。此举将意味着纬创退…...

vue手机项目如何控制手电筒打开与关闭

要控制手电筒&#xff0c;您可以使用Vue的Device API&#xff0c;例如cordova-plugin-flashlight或vue-native-flashlight插件。以下是一些基本步骤&#xff1a; 导入手电筒插件或库。在Vue组件中创建一个手电筒对象并初始化它。使用turnOn()和turnOff()方法控制手电筒。 以下…...

电商课堂|5分钟了解电商数据分析完整流程,建议收藏!

账户效果下降&#xff0c;如何能够快速找到问题并优化调整&#xff1f; 相信百分之90%的竞价员都会说&#xff1a;“做数据分析。” 没错&#xff0c;数据分析能够帮助我们快速锁定问题所在&#xff0c;确定优化方向&#xff0c;还可以帮助我们找到流量控制的方向。那么做电商&…...

Redis测试新手入门教程

在测试过程中&#xff0c;我们或多或少会接触到Redis&#xff0c;今天就把在小破站看到的三丰老师课程&#xff0c;把笔记整理了下&#xff0c;用来备忘&#xff0c;也希望能给大家带来亿点点收获。 主要分为两个部分&#xff1a; 一、缓存技术在后端架构中是如何应用的&#…...

Linux内核是如何创建进程?

目录 1.Linux如何创建进程 2.fork函数原理 2.1 fork函数原型 2.2 fork函数实现原理 2.3 父子进程虚拟地址空间&#xff08;mm_struct&#xff09;之间的关系 2.4 写时拷贝&#xff08;copy-on-write&#xff09;技术 2.5 父子进程如何共享文件&#xff08;files_struct&…...

IDEA 使用技巧

文章目录 语言支持简化编写 有问题&#xff0c;可暂时跳过 个人常用快捷键插件主题插件功能插件 碰到过的问题 除了一些在Linux上用vim开发的大佬&#xff0c;idea算是很友好的集成开发工具了&#xff0c;功能全面&#xff0c;使用也很广泛。 记录一下我的 IDEA 使用技巧&#…...

安防监控项目---web网页通过A9控制Zigbee终端节点的风扇

文章目录 前言一、zigbee的CGI接口二、请求线程和硬件控制三、现象展示总结 前言 书接上期&#xff0c;我们可以看一下前面的功能设计的部分&#xff0c;网页端的控制还有一个&#xff0c;那就是通过网页来控制zigbee上的风扇节点&#xff0c;这部分的工作量是相当大的&#x…...

Ubuntu 22.04 在登录界面循环

问题描述 https://blog.csdn.net/weixin_44023406/article/details/134092271?spm1001.2014.3001.5502 接上一篇&#xff0c;磁盘满了&#xff0c;扩展空间之后能正常开机&#xff0c;进到登录界面&#xff0c;输密码3秒后又回到登录界面 分析解决问题 命令行能登录&#…...

【C++ 系列文章 -- 程序员考试 201805 下午场 C++ 专题 】

文章目录 1.1 C 题目六1.1.1 填空&#xff08;1&#xff09;详解1.1.1.1 C 纯虚函数介绍 1.1.2 填空&#xff08;2&#xff09;详解1.1.2.1 父类声明了带参构造函数1.1.2.2 子类中构造函数的构造原则 1.1.3 填空&#xff08;3&#xff09;详解1.1.4 填空&#xff08;4&#xff…...

Python如何使用datetime模块进行日期和时间的操作

目录 一、引言 二、datetime模块的基本使用 三、日期的运算 四、注意事项 总结 本文将对Python的datetime模块进行深入探讨&#xff0c;阐述如何使用该模块进行日期和时间的各种操作。我们将介绍日期和时间的基本操作&#xff0c;以及格式化、时区处理等高级操作&#xff…...

flutter之bloc使用详解

flutter中一切皆为Widget&#xff0c;因此在我们开发中&#xff0c;往往业务和UI逻辑写在一起&#xff0c;这样不利于代码维护&#xff0c;因此状态管理框架久诞生了&#xff0c;这篇就开始讲一讲Bloc。 对于Bloc库有两个&#xff0c;如下图&#xff1a; flutter_bloc其实是对…...

记一次 .NET 某工厂无人车调度系统 线程爆高分析

一&#xff1a;背景 1. 讲故事 前些天有位朋友找到我&#xff0c;说他程序中的线程数爆高&#xff0c;让我帮忙看下怎么回事&#xff0c;这种线程数爆高的情况找问题相对比较容易&#xff0c;就让朋友丢一个dump给我&#xff0c;看看便知。 二&#xff1a;为什么会爆高 1. …...

高等数学啃书汇总重难点(九)多元函数微分法及其应用

下册最重要也是个人认为偏恶心的一节&#xff08;主要东西是真不少....&#xff09;重点在于会计算偏导、能理解全微分及隐函数求导3个核心内容&#xff0c;至于后面的关于几何层面的应用&#xff0c;建议掌握计算方法即可&#xff0c;学有余力再死磕推导过程等内容~ 1.平面点集…...

Vue3前端100个必要的知识点

为什么是必要的&#xff0c;就是这100个知识点学完后&#xff0c;能独立完成一个小项目。最终能得到一个解决方案。也算是前端知识的积累。如果后面有需要的地方可以回来查。100个其实比较多&#xff0c;我会按新手老鸟&#xff0c;大神来分成3个等级&#xff0c;话不多说&…...

CCS3列表和超链接样式

在默认状态下&#xff0c;超链接文本显示为蓝色、下画线效果&#xff0c;当鼠标指针移过超链接时显示为手形&#xff0c;访问过的超链接文本显示为紫色&#xff1b;而列表项目默认会缩进显示&#xff0c;并在左侧显示项目符号。在网页设计中&#xff0c;一般可以根据需要重新定…...

vue手机项目如何控制蓝牙连接

要控制蓝牙连接&#xff0c;您需要使用Vue的蓝牙插件或库&#xff0c;例如BLE-Peripheral或cordova-plugin-ble-central。以下是一些基本步骤&#xff1a; 导入蓝牙插件或库。在Vue组件中创建一个蓝牙对象并初始化它。扫描周围的蓝牙设备并连接到所需的设备。一旦连接成功&…...

遥遥领先,免费开源的django4-vue3项目

星域后台管理系统前端介绍 &#x1f33f;项目简介 本项目前端基于当下流行且常用的vue3作为主要技术栈进行开发&#xff0c;融合了typescript和element-plus-ui&#xff0c;提供暗黑模式和白昼模式两种主题以及全屏切换&#xff0c;开发bug少&#xff0c;简单易学&#xff0c…...

视频平台跨网级联视频压缩解决方案

一、 简介 视频监控领域对带宽有着较大的需求&#xff0c;这是因为视频流需要实时占用网络带宽资源。视频监控的传输带宽是组网结构的基础保障&#xff0c;关系到视频监控的稳定性、可靠性和可拓展性等因素。例如&#xff0c;720P的视频格式每路摄像头的比特率为2Mbps&#xff…...

利用python进行数据分析 pdf

利用python进行数据分析 pdf 介绍 在现代社会中&#xff0c;随着大数据时代的到来&#xff0c;数据分析的需求越来越大。而Python作为一门简洁且易于学习的编程语言&#xff0c;具有强大的数据分析能力&#xff0c;成为了广大数据分析师的首选工具之一。本文将指导一位刚入行的…...

从MATLAB算法到MiniCPM-V-2_6模型:科学计算与AI的融合实践

从MATLAB算法到MiniCPM-V-2_6模型&#xff1a;科学计算与AI的融合实践 如果你经常和MATLAB打交道&#xff0c;可能会遇到这样的场景&#xff1a;跑完一个复杂的仿真&#xff0c;生成了几十张图表和一堆数据&#xff0c;然后需要花上半天时间&#xff0c;手动整理结果、撰写分析…...

实时手机检测-通用模型教程:如何用Gradio搭建检测界面

实时手机检测-通用模型教程&#xff1a;如何用Gradio搭建检测界面 1. 引言与模型概述 1.1 手机检测的应用价值 在现代计算机视觉应用中&#xff0c;手机检测是一个具有广泛实用场景的技术。从智能监控系统中的打电话行为识别&#xff0c;到公共场所的手机使用管理&#xff0…...

利用快马平台快速构建openclawskills技能分享网站原型

最近在构思一个技能分享平台openclawskills&#xff0c;想快速验证这个创意是否可行。传统开发流程需要搭建前后端环境、设计数据库、编写大量基础代码&#xff0c;耗时耗力。后来尝试用InsCode(快马)平台&#xff0c;发现它能大幅缩短原型开发周期&#xff0c;特别适合快速验证…...

屏幕水印是什么?有啥用?如何设置屏幕水印?「干货图文教程」

屏幕水印是什么&#xff1f;屏幕水印&#xff0c;就是在电脑屏幕上显示的文字、图案或标志&#xff0c;就像在纸上盖章一样&#xff0c;但它出现在你的屏幕上。它可以帮助你在处理敏感信息时&#xff0c;增加一层额外的安全保护。屏幕水印有啥用&#xff1f;屏幕水印在企业信息…...

水塔水位西门子S7-1200PLC和MCGS7.7联机程序博途V16,带io表和注释

水塔水位西门子S7-1200PLC和MCGS7.7联机程序博途V16&#xff0c;带io表和注释&#xff0c;V20变频器接线说明水塔水位控制是工业自动化中常见的应用场景&#xff0c;今天咱们聊聊如何用西门子S7-1200 PLC和MCGS7.7触摸屏搭个联机控制系统。实际项目中遇到过水位传感器信号跳变的…...

AI优化效果不可控?矩阵跃动数据驱动型龙虾机器人,实现搜索排名稳定提升

在AI技术深度渗透搜索优化、流量运营等领域的今天&#xff0c;开发者与企业团队普遍面临一个核心困境&#xff1a;AI优化效果飘忽不定&#xff0c;搜索排名波动剧烈、结果不可复现、异常波动无预警&#xff0c;看似高效的自动化优化&#xff0c;反而成为业务稳定推进的潜在隐患…...

嵌入式系统程序运行机制与存储器优化

嵌入式系统程序运行机制深度解析1. 程序运行基础架构1.1 冯诺依曼体系结构现代计算机系统&#xff08;包括嵌入式设备&#xff09;都基于冯诺依曼模型构建&#xff0c;该模型包含五个核心组件&#xff1a;运算器(ALU)&#xff1a;执行算术和逻辑运算控制器(CU)&#xff1a;协调…...

专业的无代码多端协同办公哪家好

在当今数字化办公的浪潮下&#xff0c;无代码多端协同办公平台成为众多企业提升办公效率、降低数字化门槛的首选。然而&#xff0c;市场上的相关产品众多&#xff0c;企业该如何选择呢&#xff1f;今天&#xff0c;我们就来详细分析一下&#xff0c;为大家推荐一款优秀的无代码…...

接口测试,接口间数据传递,数组和字符串类型

一、接口传递说明接口1:输出如下接口2:输入如下&#xff1a;接口2的入参employeeId和userName需要从接口1的出参中获取二、解决方案ApiFox脚本&#xff1a;1、接口1后置操作&#xff1a;设置环境变量如下&#xff1a;var employeeList pm.response.json().data[0].employeeLis…...

TI-92 Plus计算器超频改造与硬件分析

1. TI-92 Plus图形计算器硬件分析与超频改造1.1 设备概述与历史背景TI-92 Plus是德州仪器(Texas Instruments)于1999年推出的图形计算器产品&#xff0c;采用摩托罗拉68K系列MC68SEC000处理器作为核心运算单元。该设备采用QWERTY全键盘设计&#xff0c;配备大尺寸LCD显示屏&…...