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

news/2024/5/18 11:52:25 标签: ubuntu, udp, recvform

目录

前言

一、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.niftyadmin.cn/n/5166063.html

相关文章

基于SSM的图书管理借阅系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

ppt聚光灯效果

1.放入三张图片内容或其他 2.全选复制成图片 3.设置黑色矩形&#xff0c;透明度30% 4.粘贴复制后的图片&#xff0c;制定图层 5.插入椭圆&#xff0c;先选中矩形&#xff0c;再选中椭圆&#xff0c;点击绘图工具&#xff0c;选择相交即可&#xff08;关键&#xff09;

特殊矩阵的压缩存储(对称矩阵,三角矩阵,三对角矩阵,稀疏矩阵)

目录 1.数组的存储结构1.—维数组2.二维数组1.行优先存储2.列优先存储 2.特殊矩阵1.对称矩阵1.行优先存储 2.三角矩阵1.上三角矩阵2.下三角矩阵 3.三对角矩阵&#xff08;带状矩阵&#xff09;4.稀疏矩阵 1.数组的存储结构 1.—维数组 各数组元素大小相同&#xff0c;且物理上…

Linux 命令:PS(进程状态)

1. 写在前面 本文主要介绍&#xff1a;Linux 下常用命令 PS —— 进程状态&#xff1b; 公众号&#xff1a; 滑翔的纸飞机 2. PS — 介绍&#xff08;进程状态&#xff09; ps 命令&#xff1a;显示 Linux 系统中运行进程有关的信息。 rootdev:~# psPID TTY TIME C…

C语言初学1:详解#include <stdio.h>

一、概念 #include <stdio.h> 称为编译预处理命令&#xff0c;它在告诉C编译器在编译时包含stdio.h文件&#xff0c;如果在代码中&#xff0c;调用了这个头文件中的函数或者宏定义&#xff0c;则需引用该头文件。 二、作用 stdio.h是c语言中的标准输入输出的头文件&am…

体制内人,知道这个工具,写什么都有底气

体制内&#xff0c;每天都在写各种材料&#xff01;&#xff01; 用词、结构、形式什么的都要严谨&#xff0c;但有时候写完又不行&#xff0c;还要改改改&#xff0c;家人们谁懂啊&#xff01;&#xff01;&#xff01; 这个工具&#xff0c;输入要求就可以快速生成文案&…

群辉NAS:ARPL引导黑群晖DSM 7.2详细教程

群辉NAS&#xff1a;ARPL引导黑群晖DSM 7.2详细教程 https://baijiahao.baidu.com/s?id1767784058309148380&wfrspider&forpc

高速信号PCB布局怎么布?(电子硬件)

对于高速信号&#xff0c;pcb的设计要求会更多&#xff0c;因为高速信号很容易收到其他外在因素的干扰&#xff0c;导致实际设计出来的东西和原本预期的效果相差很多。 所以在高速信号pcb设计中&#xff0c;需要提前考虑好整体的布局布线&#xff0c;良好的布局可以很好的决定布…