C语言实现linux环境UDP协议接收发送数据

2023-05-16

C语言实现linux环境UDP协议接收发送数据

  • 说明
  • 上代码
  • 运行结果

说明

闲来无事,写了个C语言的UDP小程序,程序新建了两个线程,分别用来实现UDP数据到发送和接收。需要的直接拿去用。

上代码

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdbool.h>

#define  MAX_UDP_RCV_LEN    512
#define  LS_OK              0
#define  LS_ERR             -1
#define  TRUE               1
#define  FALSE              0


typedef struct UDP_UNICAST_ST
{
    int sockfd;
    struct sockaddr_in PeerAddr;
    char RcvBuf[MAX_UDP_RCV_LEN];
}UdpUnicastSt;

static pthread_t    keepAliveThreadId;
static UdpUnicastSt g_udpUnicast;
static pthread_t    NetWorkUdpUnicastThreadId1;
static pthread_t    NetWorkUdpUnicastThreadId2;


/***************************************************************************
function: setThreadAttr
input:
output:
Description:
****************************************************************************/
void setThreadAttr(pthread_attr_t *thread_attr, unsigned int priority, size_t stack_size)
{
    size_t StackSize = 0;

    pthread_attr_init(thread_attr);//首先需要对属性变量进行初始化
    pthread_attr_setscope(thread_attr, PTHREAD_SCOPE_PROCESS);
    pthread_attr_setdetachstate(thread_attr, PTHREAD_CREATE_JOINABLE);
    struct sched_param param;
    pthread_attr_getschedparam(thread_attr, &param);
    param.sched_priority = (int)priority;
    pthread_attr_setschedparam(thread_attr, &param);
    if(stack_size < 0x4000) //以字节为单位  最小16k
    {
      StackSize = 0x4000;
    }
    pthread_attr_setstacksize(thread_attr, StackSize);
}

void *keepAliveProcess()
{
    while(1)
    {
        printf("udp process is alive!\n");
        sleep(180);
    }
}

/***************************************************************************
function: createThread
input:
output:
Description:提供统一线程创建函数
****************************************************************************/
int createThread(pthread_t *thread_id, const pthread_attr_t *attr, void *(*thread_fun) (void *), void *thread_arg)
{
    int ret = -1;
    ret = pthread_create(thread_id, attr, thread_fun, thread_arg);
    return ret;
}

/***************************************************************************
function: keepAliveThread
input:
output:
Description:
****************************************************************************/
static int keepAliveThread(void)
{
    int ret = -1;
    pthread_attr_t Thread_Attr;


    setThreadAttr(&Thread_Attr, 11, 0x8000);

    ret = createThread(&keepAliveThreadId, &Thread_Attr, keepAliveProcess, NULL);
    if(ret != 0)
    {
        printf("keepAliveThread failed!\n");
    }

    return ret;
}

void threadWaitDone(void **reval)
{
    pthread_join(keepAliveThreadId, reval);
}


/***************************************************************************
function: UdpUnicastInit
input:
output:
Description:udp socket初始化
****************************************************************************/
int UdpUnicastInit()
{
    int ret = -1;

    g_udpUnicast.sockfd = socket(AF_INET,SOCK_DGRAM, 0);
    if (g_udpUnicast.sockfd < 0)
    {
        printf("Create UDP socket failed!\n");
        return LS_ERR;
    }

    struct sockaddr_in LocalAddr;
    memset(&LocalAddr, 0, sizeof(struct sockaddr_in));
    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_port = htons(13903);  //临时指定为13903,征途智能门锁有线传感器
    LocalAddr.sin_addr.s_addr = INADDR_ANY;

    ret = bind(g_udpUnicast.sockfd, (struct sockaddr *)(&LocalAddr), sizeof(struct sockaddr));
    if (-1 == ret)
    {
        close(g_udpUnicast.sockfd);
        g_udpUnicast.sockfd = -1;
        return LS_ERR;
    }
    return LS_OK;
}

/***************************************************************************
function: modbusMsgPrint
input:
output:
Description:打印串口数据
****************************************************************************/
void modbusMsgPrint(unsigned char *pBuffer, int buffLen, bool bRcvFlag)
{
    if(NULL == pBuffer || 0 == buffLen)
    {
        return;
    }

    char szPrint[4096] = {0};
    int i = 0;
    for(i = 0;i < buffLen; i++)
    {
        snprintf(&(szPrint[strlen(szPrint)]),4096 - strlen(szPrint)," 0x%02X",pBuffer[i]);
    }

    if(bRcvFlag)
    {
        printf("Rcv:%s.\n",szPrint);
    }
    else
    {
        printf("Send:%s.\n",szPrint);
    }
}
/***************************************************************************
function: NetWorkUdpUnicastSendThread
input:
output:
Description:udp数据发送线程
****************************************************************************/
void* NetWorkUdpUnicastSendThread(void *param)
{
    socklen_t     addrLen      = 0;
    unsigned char sendBuff[64] = {1,1,2,2,3,3,4,4,5};
    int           recvRet      = 0;
    struct sockaddr_in LocalAddr;

    addrLen = sizeof(struct sockaddr);
    memset(&LocalAddr, 0, sizeof(struct sockaddr_in));
    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_port   = htons(13903);  //临时指定为13903

    printf("start NetWorkUdpUnicastSendThread....!\n");
    while(1)
    {

        LocalAddr.sin_addr.s_addr = inet_addr("192.168.8.28");//临时指定为192.168.90.56
        recvRet = (int)sendto(g_udpUnicast.sockfd, sendBuff, 11, 0, (struct sockaddr*)&LocalAddr, addrLen);
        printf("UDP send %d data: %s\n", recvRet, sendBuff);
        modbusMsgPrint(sendBuff, recvRet, FALSE);
        sleep(60);
    }
}

/***************************************************************************
function: NetWorkUdpUnicastRecvThread
input:
output:
Description:udp数据接收线程
****************************************************************************/
void* NetWorkUdpUnicastRecvThread(void *param)
{
    int           recvRet     = -1;
    socklen_t     addrLen     = 0;

    addrLen = sizeof(struct sockaddr);

    printf("start NetWorkUdpUnicastRecvThread....!\n");
    while(1)
    {
        recvRet = (int)recvfrom(g_udpUnicast.sockfd, g_udpUnicast.RcvBuf, MAX_UDP_RCV_LEN - 1,0,(struct sockaddr*)(&g_udpUnicast.PeerAddr),&addrLen);
        if (-1 == recvRet)
        {
            printf("UDP recv data failed!\n");
            continue;
        }

        printf("UDP recv %d data: %s\n", recvRet, g_udpUnicast.RcvBuf);
        modbusMsgPrint((unsigned char *)g_udpUnicast.RcvBuf, recvRet, TRUE);
    }
}


/***************************************************************************
function: NetWorkUdpUnicastInit
input:
output:
Description:udp客户端创建初始化
****************************************************************************/
int netWorkUdpUnicastInit()
{
    int ret = -1;
    pthread_attr_t Thread_Attr1;
    pthread_attr_t Thread_Attr2;

    memset(&g_udpUnicast, 0,sizeof(UdpUnicastSt));

    ret = UdpUnicastInit();
    if(LS_OK != ret)
    {
      printf("UDP Socket init failed!\n");
      return LS_ERR;
    }

    setThreadAttr(&Thread_Attr1,20,0x8000);
    ret = createThread(&NetWorkUdpUnicastThreadId1, &Thread_Attr1, NetWorkUdpUnicastSendThread, NULL);
    if(ret != 0)
    {
        printf("Create network udp send thread failed!\n");
        return LS_ERR;
    }
    setThreadAttr(&Thread_Attr2,20,0x8000);
    ret = createThread(&NetWorkUdpUnicastThreadId2, &Thread_Attr2, NetWorkUdpUnicastRecvThread, NULL);

    if(ret != 0)
    {
        printf("Create network udp recv thread failed!\n");
        return LS_ERR;
    }

    return LS_OK;
}


int main()
{
    printf("---udp process start---\n");
    void *thread_reval = NULL;

    //udp
    netWorkUdpUnicastInit();

    //进程保活
    keepAliveThread();

    threadWaitDone(&thread_reval);
    if(thread_reval != NULL)
    {
        printf("thread_reval : %s is not null\n", (char *)thread_reval);
    }
    //不会运行至此
    printf("---udp process end---\n");
    return 0;
}

运行结果

linux环境下运行进程或者直接QT编译运行,这里的结果展示为centos虚拟机的QT运行。
虚拟机ip为192.168.8.235,程序里UDP的端口写死的13903。
宿主机的ip为192.168.8.28,运行一个UDP的模拟工具。
本程序定时发送一串字节流,模拟工具可以正常接收。
在这里插入图片描述
模拟工具发送字节流,程序也可以正常接收显示。
在这里插入图片描述
打完收工。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言实现linux环境UDP协议接收发送数据 的相关文章

  • pixhawk之NSH调试

    一 ardupilot固件 windows环境 前期准备 1 xff1a pix烧录程序 xff0c Arducopter或者library中的example都可以实现 2 xff1a 拔掉SD卡 xff08 脚本中提到的没有SD卡进入ns
  • 目标检测(yolov3)实现---darknet的C语言版本

    环境安装 ubuntu opencv cuda cudnn gt920m 参考 https blog csdn net qq 36362060 article details 80739573 darknet github地址 https
  • C++PrimerPlus学习笔记——第9章内存模型和名称空间(最全最详细)

    注 xff1a 这一章都是理解记忆性的内容 xff0c 因此笔者在某些知识点会将自己的理解话语写上 xff0c 便于可读性和方便理解 本章内容包括 xff1a 单独编译 xff1b 存储持续性 作用域和链接性 xff1b 定位 xff08
  • 图论——拓扑排序及最短路径算法模板

    一 拓扑排序 span class token comment 将入度为0的点写入myQueue span vector span class token operator lt span span class token keyword
  • 2022 PAT 甲级秋 100分

    PAT2022秋 有一题是卡着时间复杂度去做的结果AC了 希望大家也能来一起交流下最优解 踩气球 AC 这道题调试了很久 才开始用的哈希表内存太大了 span class token macro property span class to
  • 十大排序 C++代码

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • 位运算实现加减乘除、交换

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • 智能指针模拟实现C++

    span class token keyword template span span class token operator lt span span class token keyword typename span span cla
  • 转:卷积神经网络的卷积核大小、个数,卷积层数如何确定呢?

    卷积神经网络的卷积核大小 卷积层数 每层map个数都是如何确定下来的呢 xff1f 看到有些答案是刚开始随机初始化卷积核大小 xff0c 卷积层数和map个数是根据经验来设定的 xff0c 但这个里面应该是有深层次原因吧 xff0c 比如下
  • 生产者消费者模型c++

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • 关于vscode断点调试

    很多人习惯在 Chrome 的调试窗口中调试 Vue 代码 xff0c 或者直接使用 console log 来观察变量值 xff0c 这是非常痛苦的一件事 xff0c 需要同时打开至少 3 个窗体 个人还是更加习惯于断点调试 这篇文章将介
  • 斐讯T1电视盒子刷机指南,已排大坑

    斐讯T1刷机详细指南 xff0c 老手直接看小标题的括号 1 准备好一些文件 xff08 中心思想就是刷写工具 降级img 新系统img xff09 1 0 你需要准备一条双usb头的线 1 1 新系统固件 1 2 斐讯T1官方系统降级文件
  • 关于在conda环境下,pip已安装好包,但是python import错误的解决方法

    1 pip uninstall 那个包 2 conda install 那个包 或者 复制系统python目录下的Lib gt site packages文件夹覆盖conda虚拟环境下的对应文件夹 原因 xff1a pip为系统的pip x
  • win10 系统 U盘无法删除卷

    我的一个U盘折腾来折腾去 xff0c 现在用win10 自带分区磁盘管理的时候 xff0c 右键U盘 删除卷 xff0c 显示不支持该请求 解决办法 xff1a 1 cmd中运行diskpart 2 lisk disk 3 sel disk
  • termux 修改自定义字体

    需要先安装termux styling termux 运行chfont可修改预设的二十几种字体 xff0c 接下来的操作可以添加自己的字体 将字体文件复制到 termux fonts 里 xff0c 再运行chfont就能看到自己的字体了
  • windows平台,mingw64编译环境下的socket使用

    代码并不重要 xff0c 主要看最后的编译命令 xff1a span class token comment test cpp span span class token macro property span class token di
  • [有/无]刷,[直/交]流,[同/异]步,各种电机概念区分

    本质上 xff0c 所有的电机都是交流电机 直 交流电机 xff0c 通常是俗语 要想让电机转子转起来 xff0c 任何电机的绕组都要不断地改变电流方向 xff0c 电流大小呈正弦波或者方波 xff08 方波也可看做正弦波近似 xff09
  • opencv 快速简单二值化的做法

    大家在网上搜索opencv二进制 xff0c 很多人会告诉你用threshold等函数 这类函数虽然支持自适应等功能 xff0c 但是参数比较多 xff0c 有点复杂 我们只要简单二值化的时候可以用以下做法 xff1a Mat img sp
  • ubuntu18.04 使用systemd方式添加开机运行sh脚本

    ubuntu18 04压根就没有rc local xff0c 而且很多发行版都推荐使用systemd而不是initd了 1 准备好你的sh脚本文件 内容略过 xff0c 就假设路径是 usr local my my sh吧 别忘了chmod
  • 转:安装了anaconda不需要安装CUDA和cuDNN

    我电脑i7 1060 xff0c 之前一直在找匹配的cuda和cudnn xff0c 安装出现各种问题 xff0c 直到高人提醒 xff0c anaconda自带cuda和cudnn 我打开开始菜单里的anaconda里的navigator

随机推荐