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

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的模拟工具。
本程序定时发送一串字节流,模拟工具可以正常接收。
C语言实现linux环境UDP协议接收发送数据_第1张图片
模拟工具发送字节流,程序也可以正常接收显示。
C语言实现linux环境UDP协议接收发送数据_第2张图片
打完收工。

你可能感兴趣的:(C语言,udp,c语言,linux)