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

目录

前言

一、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接收不到广播报文的情况,可以参考本文内容解决。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第三章 UI开发的点点滴滴

一、常用控件的使用方法 1.TextView android:gravity"center" 可选值&#xff1a;top、bottom、left、right、center等&#xff0c;可以用"|"来同时指定多个值&#xff0c;center表示文字在垂直和水平方向都居中 android:textSize 指定文字的大小&#…

双十一数码好物推荐,盘点那些错过等一年的好物!

双十一购物狂欢节马上到来&#xff0c;对于热爱数码产品的人来说&#xff0c;双十一无疑是一个绝佳的时机&#xff0c;因为许多知名品牌和零售商都会推出各种令人心动的数码好物促销活动。从佩戴服饰到大件智能装备&#xff0c;再到健康科技产品&#xff0c;市场上的选择多种多…

ASUS华硕灵耀X2 Duo UX481FA(FL,FZ)_UX4000F工厂模式原装出厂Windows10系统

下载链接&#xff1a;https://pan.baidu.com/s/1sRHKBOyc3zu1v0qw4dSASA?pwd7nb0 提取码&#xff1a;7nb0 带有ASUS RECOVERY恢复功能、自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、MyASUS华硕电脑管家等预装程序所需要工具&#xff1a;16G或以上…

【mongoose】mongoose 基本使用

1. 连接数据库 // 1. 安装 mongoose // 2. 导入 mongoose const mongoose require(mongoose) // 3. 连接 mongodb 服务 mongoose.connect(mongodb://127.0.0.1:27017/xx_project) // 4. 设置回调 .on 一直重复连接 .once 只连接一次 mongoose.connection.on(open, () >…

【MySQL】一文学会所有MySQL基础知识以及基本面试题

文章目录 前言 目录 文章目录 前言 一、主流数据库以及如何登陆数据库 二、常用命令使用 三、SQL分类 3.1 存储引擎 四、创建数据库如何设置编码等问题 4.1操纵数据库 4.2操纵表 五、数据类型 六、表的约束 七、基本查询 八、函数 九、复合查询 十、表的内连和外连 十一、索引…

Flink之状态管理

Flink状态管理 状态概述状态分类 键控、按键分区状态概述值状态 ValueState列表状态 ListStateMap状态 MapState归约状态 ReducingState聚合状态 Aggregating State 算子状态概述列表状态 ListState联合列表状态 UnionListState广播状态 Broadcast State 状态有效期 (TTL)概述S…

JSON——数组语法

一段JSON可能是以 ”{“ 开头 也可能仅包含一段JSON数组 如下 [ { "name" : "hello,world"}, {"name" : "SB JSON”}&#xff0c; {“name” : "SB互联网房地产CNM“}&#xff0c; ] 瞧&#xff0c;蛋疼不...CJSON过来还是得搜下网…

持续集成交付CICD:安装Gitlab Runner(从节点)

目录 一、实验 1.选择Gitlab Runner版本 2.安装Gitlab Runner&#xff08;第一种方式&#xff1a;交互式安装&#xff09; 3.安装Gitlab Runner&#xff08;第二种方式&#xff1a;非交互式安装&#xff09; 二、问题 1.如何查看Gitlab版本 一、实验 1.选择Gitlab Runne…

『 MySQL数据库 』数据库基础之库的基本操作

文章目录 库的操作创建数据库字符集与校验集那么该如何查看当前数据库默认的字符集与校验规则?查看数据库所支持的字符集与校验集不同字符集(校验集)之间的区别 基本操作查看数据库显式数据库创建语句数据库的修改数据库的删除数据库的备份检查连接 库的操作 创建数据库 CRE…

【ES专题】ElasticSearch功能详解与原理剖析

目录 前言要点阅读对象阅读导航前置知识笔记正文一、ES数据预处理1.1 Ingest Node&#xff1a;摄入节点1.2 Ingest Pipeline&#xff1a;摄入管道1.3 Processor&#xff1a;预处理器——简单加工1.4 Painless Script&#xff1a;脚本——复杂加工1.5 简单实用案例 二、文档/数据…

网际报文协议ICMP及ICMP重定向实例详解

目录 1、ICMP的概念 2、ICMP重定向 3、利用ICMP重定向进行攻击的原理 4、如何禁止ICMP重定向功能&#xff1f; 4.1、在Linux系统中禁用 4.2、在Windows系统中禁用 5、关于ICMP重定向的问题实例 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xf…

数据结构与算法—插入排序选择排序

目录 一、排序的概念 二、插入排序 1、直接插入排序 直接插入排序的特性总结&#xff1a; 2、希尔排序 希尔排序的特性总结&#xff1a; 三、选择排序 1、直接选择排序 时间复杂度 2、堆排序—排升序(建大堆) 向下调整函数 堆排序函数 代码完整版&#xff1a; …

VUE多语言i18n配置

1、i18n官网 格式化 | Vue I18n 2、安装i18n 8---指版本号 // vue2必须安装8版本的i18n包&#xff0c;vue3必须安装9版本的i18n包。 npm i vue-i18n8 3、卸载i18n npm uninstall vue-i18n 4、安装 js-cookie npm install vue-cookies --save 5、代码 5.1 main.js /…

GPT出现了Something went wrong.

网络上的一种说法如下

数据结构(超详细讲解!!)第二十二节 广义表

1.定义 广义表&#xff0c;顾名思义&#xff0c;也是线性表的一种推广。广义表被广泛地应用于人工智能等领域的表处理语言LISP语言中。在LISP语言中&#xff0c;广义表是一种最基本的数据结构&#xff0c;就连LISP 语言的程序也表示为一系列的广义表。 广义表又称列表&#x…

11.(vue3.x+vite)组件间通信方式之ref与$parent、$children

前端技术社区总目录(订阅之前请先查看该博客) 示例效果 注: (1)ref 加在标签(div等)上,是拿到dom 对象 (2)ref加上组件上,拿到的是组件的引用 (3)让父组件获取子组件的数据或者方法需要通过defineExpose对外暴露,另外让父组件获取子组件的数据或者方法需要通过d…

NIO 笔记(一)基础内容

【笔记来自&#xff1a;it白马】 NIO基础 **注意&#xff1a;**推荐完成JavaSE篇、JavaWeb篇的学习再开启这一部分的学习&#xff0c;如果在这之前完成了JVM篇&#xff0c;那么看起来就会比较轻松了。 在JavaSE的学习中&#xff0c;我们了解了如何使用IO进行数据传输&#xf…

C语言每日一题(27)链表中倒数第k个结点

牛客网 链表中倒数第k个结点 题目描述 描述 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 思路分析 这是一道经典的快慢指针题&#xff0c;fast和slow最开始都指向头结点&#xff0c;对于输入值k&#xff0c;先让快指针fast先走k步&#xff0c;之后再让两个指针一…

ABAP Json和对象的转换

se24新建类ZCL_JSON保存 点击修改&#xff0c;进入下图界面&#xff0c;点击红框。 复制粘贴下面代码 CLASS zcl_json DEFINITIONPUBLICCREATE PUBLIC .PUBLIC SECTION. *"* public components of class ZCL_JSON *"* do not include other source files here!!!TYP…

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

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