闲来无事,写了个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, ¶m);
param.sched_priority = (int)priority;
pthread_attr_setschedparam(thread_attr, ¶m);
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的模拟工具。
本程序定时发送一串字节流,模拟工具可以正常接收。
模拟工具发送字节流,程序也可以正常接收显示。
打完收工。