ubuntu18-recvfrom接收不到广播报文异常分析

news2024/11/24 3:28:22

目录

前言

一、UDP广播接收程序

二、异常原因分析

总结


前言

        在ubuntu18.04系统中,编写udp接收程序发现接收不到广播报文,使用抓包工具tcpdump可以抓取到广播报文,在此对该现象分析解析如下文所示。

一、UDP广播接收程序

        UDP广播接收程序如下所示,广播发送程序使用上位机向255.255.255.255地址11100端口发送广播报文。

int CreateUdpSocket(int iUdpPort)
{
    int flag = 1;
    int err;
    int iSockFd = 0;
    short sPort = (short)iUdpPort;
    struct sockaddr_in tSockAddr;
    
	
    iSockFd = socket(AF_INET, SOCK_DGRAM, 0);
    if (iSockFd <= 0)
    {
        printf("[%s]Create local socket Error.\n", __FUNCTION__);
        return -1;
    }

    tSockAddr.sin_family      = AF_INET;
    tSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    tSockAddr.sin_port        = htons(sPort);
	
    err = setsockopt(iSockFd, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(int));
    if(err != 0)
    {
        printf("ERR: setsockopt  socket error. err = %d,errno = %d[%s] port %d\n",err, errno, strerror(errno), iUdpPort);
        close(iSockFd);
        return -2;
    }
    if (bind(iSockFd, (struct sockaddr*)&tSockAddr, sizeof(struct sockaddr_in)) < 0)
    {
        printf("ERR:  bind error.\n");
        close(iSockFd);
        return -3;
    }
    
    return iSockFd;
}

void *StartBroadCastThread(void *arg)
{
    char acInterface[] = "eth0";
    int ifindex = 0;
    int iSocket = -1;
    int iLen = 10000;
    int iRet = 0;
    int iBroadcastIface = -1;
    int iEthIndex = 0;
    int iEthNum = 0;
    int i;
    unsigned char *pcData = NULL;
    struct sockaddr_in tSockAddr;
    int iSockAddrLen = sizeof(tSockAddr);
    int iRecvLen = 0;
    short sSendLen = 0;
    PT_MSG_INFO ptMsg = NULL;
    T_MSG_BROADCAST_DEV_INFO *ptBroadCastInfo = NULL;
    //T_ETHNAME_INFO atEthNameInfo[MAX_ETH_NUM];
 //   T_DEV_NET_INFO *ptNetInfo = NULL;
    char acBroadcastIface[24];
    char acTmpBuf[512];
    int iSessionId = 0;
    T_ETHNAME_INFO atEthNameInfo[4];
    
    iSocket = CreateUdpSocket(MSG_TEST_BROADCAST_PORT);
    if (iSocket < 0)
    {
        printf("socket udp failed\n");
        return NULL;
    }
    
    pcData = (char *)malloc(iLen);
    if (NULL == pcData)
    {
        printf("[%s] malloc failed\n", __FUNCTION__);
        close(iSocket);
        return NULL;
    }
    
    //ptHead = (PT_MSG_HEAD)pcBuf;
    while (1)
    {
        iRecvLen = recvfrom(iSocket, pcData, iLen, 0, 
                                   (struct sockaddr *)&tSockAddr, (socklen_t*)&iSockAddrLen);
        if(iRecvLen <= 0)
        {
            printf("[%s] recvfrom fail, .\n", __FUNCTION__);
            close(iSocket);
            free(pcData);
            return NULL;
        }
        if (iRecvLen < 4)
        {
            printf("iRecvLen = %d\n", iRecvLen);
            continue;
        }
        printf("[%s]recv len %d, magic %d, cmd %d\n", __FUNCTION__, iRecvLen, pcData[0], pcData[1]);
        if ((pcData[0] == MSG_MAGIC_FLAG) && (pcData[1] == MSG_CLI2SERV_BROADCAST_QUERY))
        {
        	  printf("[%s]%d\n", __FUNCTION__, __LINE__);
        	  memset(pcData, 0, iLen);
            ptMsg = (PT_MSG_INFO)pcData;
            ptBroadCastInfo = (T_MSG_BROADCAST_DEV_INFO *)ptMsg->acMsgData;
           /* srand((int)time(0));
            iSessionId = (int)(300000.0*rand()/(RAND_MAX+1.0));
            memset(ptBroadCastInfo, 0, sizeof(T_MSG_BROADCAST_DEV_INFO));
            
            ptBroadCastInfo->iSessionId = htonl(iSessionId);*/
            

            iRet =  ABI_GetDevInfo((char *)ptBroadCastInfo, sizeof(T_MSG_BROADCAST_DEV_INFO));
            
            iRet = COMM_GetNetWorkCardNum(&iEthNum, atEthNameInfo);
            if (iRet < 0)
            {
                printf("Get None NetWork Card\n");
                continue;
            }

            for (i = 0; i < iEthNum; i++)
            {
                sSendLen = sizeof(T_MSG_BROADCAST_DEV_INFO);
                ptMsg->tMsgHead.magic = MSG_MAGIC_FLAG;
                ptMsg->tMsgHead.cmd = MSG_SERV2CLI_BROADCAST_QUERY_RESP;
                ptMsg->tMsgHead.sLen = htons(sSendLen);
                COMM_GetIpAddr(atEthNameInfo[i].acName, ptBroadCastInfo->acIpAddr, sizeof(ptBroadCastInfo->acIpAddr));
                read_interface(atEthNameInfo[i].acName, &ifindex, NULL, NULL);
                send_broadcast(ifindex, MSG_TEST_BROADCAST_PORT, ntohs(tSockAddr.sin_port), pcData, sizeof(T_MSG_HEAD) + sSendLen);
            }   
        }
    }
    
    close(iSocket);
    if (pcData)
    {
        free(pcData);
        pcData = NULL;
    }
    
    return NULL;
}

使用tcpdump抓包工具可以抓到广播报文:

但是通过recvfrom函数则接收不到该报文。

二、异常原因分析

        考虑到ubuntu可以自带防火墙,但是通过查询ubuntu系统的防火墙功能,发现并没有开启,通过查询相关资料,发现可能跟Linux内核网络参数的设置有关,涉及到反向路径过滤,在/etc/sysctl.conf中有反向路径过滤参数可以设置,两项参数如下所示:

# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
#net.ipv4.conf.default.rp_filter=0
#net.ipv4.conf.all.rp_filter=0

两项参数解释如下:

  1. net.ipv4.conf.default.rp_filter=0: 这个设置表示在默认的网络接口上关闭反向路径过滤。反向路径过滤用于验证从系统收到的数据包是否通过与内核期望的相同的网络接口返回。将其设置为0表示禁用反向路径过滤。

  2. net.ipv4.conf.all.rp_filter=0: 这个设置表示在所有网络接口上关闭反向路径过滤。与前一个设置不同,这个设置应用于系统上的所有网络接口。

        由于上位机软件发送该广播报文时并没有绑定源地址,且此时ubuntu系统是默认开启源地址验证,则该报文则被系统方向过滤掉了。鉴于该种情况,在ubuntu系统中关闭反向路径过滤即可,如下:

重启ubuntu系统,在此运行程序时发现recvform可以接收到该广播报文。


总结

        在ubuntu系统如果碰到recvform接收不到广播报文的情况,可以参考本文内容解决。

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

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

相关文章

Qt工程打包工具 windeployqt 的用法

1.复制工程下的“Debug”或者“Release”文件夹到你喜欢的路径&#xff0c;例如&#xff1a;D:\QT_out\ 2.在操作系统“开始”选项找到“Qt”文件夹&#xff0c;打开“Qt 5.15.2&#xff08;MSVC 2019 64-bit&#xff09;” 重点&#xff1a; 这里要注意的是&#xff0c;一定…

osg之黑夜背景地月系显示

目录 效果 代码 效果 代码 /** * Lights test. This application is for testing the LightSource support in osgEarth. * 灯光测试。此应用程序用于测试osgEarth中的光源支持。 */ #include "stdafx.h" #include <osgViewer/Viewer> #include <osgEarth/N…

基于pytorch使用特征图输出进行特征图可视化

使用特征图输出进行特征图可视化 文章目录 前言效果展示获取某一层特征图输出原图方法一&#xff1a;使用IntermediateLayerGetter类方法二&#xff1a;使用hook机制&#xff08;推荐&#xff09; 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例…

Redis系列之实现分布式自增主键

软件环境 JDK 1.8 SpringBoot 2.2.1 Maven 3.2 Mysql 8.0.26 redis 6.2.14 Mybatis Plus 3.4.3.4 开发工具 IntelliJ IDEA smartGit 一、实现原理 使用Redis来实现分布式的主键自增主要是依赖于Redis的INCR命令&#xff0c;调用INCR命令的对应key&#xff0c;其数值…

nginx图片资源管理转发

目标: 服务器上面 /home/images 里面作为文件资源管理器 代码: server {listen 80;server_name hello.world.cn;#apple-app和接口的关联文件location ~.*(images/miniapp)*\.(gif|jpg|jpeg|png)$ {root /home/;try_files $uri $uri/ 404;add_header Cache-Control &q…

垂直领域大模型落地思考

相比能做很多事&#xff0c;但每件事都马马虎虎的通用大模型&#xff1b;只能做一两件事&#xff0c;但这一两件事都能做好&#xff0c;可被信赖的垂直大模型会更有价值。这样的垂直大模型能帮助我们真正解决问题&#xff0c;提高生产效率。 本文将系统介绍如何做一个垂直领域…

某银行软件测试笔试题,满分一百你能得多少分?

&#xff08;时间90分钟&#xff0c;满分100分&#xff09; 考试要求&#xff1a;计算机相关专业试题 一、填空题&#xff08;每空1分&#xff0c;共10分&#xff09; 1. ______验证___是保证软件正确实现特定功能的一系列活动和过程。 2. 按开发阶段分&#xff0c;软件测试可…

暖通空调系统使用Modbus转Profinet网关应用配置案例

PLC通过兴达易控Modbus转Profinet网关&#xff08;XD-MDPN100)控制暖通空调的温度、湿度。作为控PLC可以通过Modbus传输到Profinet网关&#xff0c;与空调系统的压缩机进行通信&#xff0c;从而准确控制单元的加热、加湿、冷却和减湿。PLC可以实时监控和调整空调系统的运行状态…

java版本转换小工具

工作之余写了一个转换小工具&#xff0c;具有以下功能&#xff1a; 时间戳转换Base64编码/解码URL编码/解码JSON格式化 时间戳转换 package org.binbin.container.panel;import javax.swing.*; import java.awt.*; import java.text.DateFormat; import java.text.SimpleDat…

C语言 预处理详解

目录 1.预定义符号 2.#define 2.1#define 定义标识符 2.2#define 定义宏 2.3#define 替换规则 2.4#和## 2.4.1# 的作用 2.4.2## 的作用 2.5 带有副作用的宏参数 2.6宏和函数的对比 对比 **2.7内联函数 2.8命名约定 3.#undef **4.命令行定义 5.条件编译 常…

李开复创业公司零一万物开源迄今为止最长上下文大模型:Yi-6B和Yi-34B,支持200K超长上下文

本文来自DataLearnerAI官方网站&#xff1a;李开复创业公司零一万物开源迄今为止最长上下文大模型&#xff1a;Yi-6B和Yi-34B&#xff0c;支持200K超长上下文 | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051699285770532 零一万物&#xff08;01.AI…

C语言 每日一题 11.9 day15

数组元素循环右移问题 一个数组A中存有N&#xff08; > 0&#xff09;个整数&#xff0c;在不允许使用另外数组的前提下&#xff0c;将每个整数循环向右移M&#xff08;≥0&#xff09;个位置&#xff0c;即将A中的数据由&#xff08;A0​A1⋯AN−1&#xff09;变换为&…

爱剪辑如何将视频旋转90度,详细操作流程

爱剪辑是一款电脑端常用的视频剪辑类软件&#xff0c;基本上囊括了视频剪辑所需的所有功能&#xff0c;此处主要介绍&#xff0c;爱剪辑是如何对视频进行旋转操作的&#xff0c;水平旋转或者垂直旋转爱剪辑都是可以操作的&#xff0c;整体操作的详细过程将在下方为大家讲解。 …

Linux进程控制(2)

Linux进程控制(2) &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解了进程等待收尾内容和进程的程序…

【Codeforces】Codeforces Round 905 (Div. 3)

Problem - 1883C - Codeforces 这题当时想复杂了。 题目大意&#xff1a; 给一串数组和一个数字k&#xff0c;求对数组进行多少次操作能是他们的乘积是k的倍数。 操作是选定一个数加上1。 这题需要抓住一个点k属于[2,5]&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5中…

python连接mysql进行查询

pymysql连接工具类 import pymysql 数据库连接工具类 class MySQLConnection:def __init__(self, host, port, user, password, database):self.host hostself.port portself.user userself.password passwordself.database databaseself.conn Noneself.cursor None# …

Umdh进行内存泄露分析软件的下载、安装与使用

1 下载与安装 1.1 软件介绍 Umdh一款轻量级的内存泄露分析工具UMDH&#xff08;User-Mode Dump Heap&#xff09;&#xff0c;是 Debugging Tools for Windows 里面的一个工具&#xff0c;主要通过分析比较进程的Heap Stack trace信息来发现内存泄露。 Umdh内存泄露分析适用…

Spring Boot 请求/actuator/beans 无法访问 返回404

问题复现 在保证项目加入了spring-boot-starter-actuator依赖&#xff0c;并成功启动后。通过浏览器进行访问&#xff0c;返回如下图结果&#xff1a; 问题排查 1. 查看日志 从日志中可以看到基于路径’/actuator’下只暴露了一个端点 2. 访问http://localhost:8080/actua…

【309. 买卖股票的最佳时机含冷冻期】

目录 一、题目解析 二、算法原理 三、代码实现 class Solution { public:int maxProfit(vector<int>& prices) {int nprices.size();vector<vector<int>> dp(n,vector<int>(3));dp[0][0]-prices[0];dp[0][1]0;dp[0][2]0;for(int i1;i<n;i){dp…

HTML的表单标签和无语义标签的讲解

HTML的表单标签 表单是让用户输入信息的重要途径, 分成两个部分: 表单域: 包含表单元素的区域. 重点是 form 标签. 表单控件: 输入框, 提交按钮等. 重点是 input 标签 form 标签 使用form进行前后端交互.把页面上,用户进行的操作/输入提交到服务器上 input 标签 有很多形态,能…