linux关闭udp线程,linux下c++多线程详解,应用于UDP

本文详细介绍了如何使用pthread库在C/C++中创建并管理多线程,以实现实时UDP数据的接收和处理。通过实例演示了线程创建、join、锁机制的应用,以及如何结合UDP协议进行高效并发操作,适合进一步开发和调试工作。
摘要由CSDN通过智能技术生成

本文使用pthread的库,调用其中API可方便实现多线程效果。

本文主要讲解实际中用到的几个接口函数,足够一般开发使用。

实例为应用与UDP协议的收发,打开接收数据线程,接收不影响主线程,主线程进行数据处理等工作,方便二次开发。

关于UDP的教程可以参看:http://blog..net/weixin_37895339/article/details/72716774

首先介绍需要用到的接口函数。

1.pthread_create()函数

用于创建线程,调用该函数后,线程开始执行。创建成功时返回0。

int pthread_create(pthread_t *thread, const pthread_attr_t, void *(*_function)(void*), void *arg)

参数介绍:

a.第一个参数为线程id的指针,创建方式为:

pthread_t thread[Thread_Num];

将id的地址付给第一个参数:

rc = pthread_create(*thread[i],NULL,NULL,NULL);

b.第二个参数为线程属性设置,创建方式为:

pthread_attr_t attr; //线程属性设置

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); //将属性设置为joinable,可以使主线程等待该线程执行完后,再结束主线程

rc = pthread_create(*thread[i],&attr,NULL,NULL);

c.第三个参数为线程执行的函数&第四个参数为该函数需要的参数

该函数类型为 void*,即返回值为void*。参数类型为void*,如果要传递多个参数,可以建立一个结构体进行传递。示例如下:

struct thread_recdata{ //函数所需传递的参数,一共有两个,放在一个结构中

int sockfd; //socket

char *info; //接受的数据

};

thread_recdata thread_rec; //创建函数所用参数

void *recinfo(void *rec_data); //创建函数

rc = pthread_create(&thread[0], &attr ,recinfo,(void *)&thread_rec); //开启线程

pthread_attr_destroy(&attr); //释放属性attr的空间

2.pthread_join()函数

调用该函数可以阻塞主线程,等待子线程运行完后再结束主线程。如果不阻塞,可能出现主线程运行完,程序结束,但子线程还没运行完的情况。

int pthread_join(pthread_t thread,void **status_value)

d第一个参数为要等待子线程的id,第二个参数为返回的线程状态信息,其类型为void*。实例为:

void *status;

rc = pthread_join(thread[i], &status);

if (rc){

printf("Error:unable to join");

exit(-1);

}

3.线程锁

当两个线程同时调用修改同一个数据变量时,必须加线程锁,否则将会出现数据错乱的情况。数据加锁后,其余调用该变量的线程将会被阻塞,直到释放锁。实例如下:

pthread_mutex_t rec_mutex; //创建线程锁

pthread_mutex_lock(&rec_mutex); //加锁

rec_queue.push(thread_info->info); //修改数据

pthread_mutex_unlock(&rec_mutex); //解锁

下面介绍一个应用于UDP协议的多线程实例:

本例打开一个接受线程不断接受外部发来的数据,主线程处理这些数据,另开一个显示线程用作调试。方便二次开发。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define port_in 12321

#define port_out 12322

#define Num_Thread 3

char info_rec[10][128];

pthread_mutex_t rec_mutex; //线程锁

struct thread_senddata{

int sockfd; //socket

char *info; //发送的数据

char *addr; //发送的地址

int port; //发送的端口

};

struct thread_recdata{

int sockfd; //socket

char *info; //接受的数据

};

int initudp(void)

{

int sockfd;

/* Create Socket*/

sockfd = socket(AF_INET, SOCK_DGRAM, 0);

if(-1==sockfd){

return 0;

puts("Failed to create socket");

}

/*Config Socket Addr*/

struct sockaddr_in addr;

socklen_t addr_len=sizeof(addr);

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET; // Use IPV4

addr.sin_port = htons(port_in); //

addr.sin_addr.s_addr = inet_addr("10.106.2.146");

/* Time out*/

// struct timeval tv;

// tv.tv_sec = 0;

// tv.tv_usec = 200000; // 200 ms

// setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(struct timeval));

/* Bind Socket*/

if (bind(sockfd, (struct sockaddr*)&addr, addr_len) == -1){ //收数据才需要bind

printf("Failed to bind socket on port %d\n", port_in);

close(sockfd);

return false;

}

return sockfd;

}

void sendinfo(thread_senddata *thread_info) //发送数据调用

{

int len;

struct sockaddr_in dest;

socklen_t dest_len = sizeof(dest);

memset(&dest, 0, sizeof(dest));

dest.sin_family = AF_INET;

dest.sin_port = htons(thread_info->port);

dest.sin_addr.s_addr = inet_addr(thread_info->addr);

if(strlen(thread_info->info)!=0) //如果数组有数则发送

{

len = strlen(thread_info->info);

sendto(thread_info->sockfd, thread_info->info, len, 0, (sockaddr*)&dest, dest_len);

}

}

void *recinfo(void *rec_data) //接受线程调用的函数

{

struct thread_recdata *thread_info;

thread_info = (struct thread_recdata *)rec_data;

struct sockaddr_in src;

socklen_t src_len = sizeof(src);

memset(&src, 0, sizeof(src));

while(1)

{

int sz = recvfrom(thread_info->sockfd, thread_info->info, 128, 0, (sockaddr*)&src, &src_len);

if (sz > 0){

thread_info->info[sz] = 0;

pthread_mutex_lock(&rec_mutex);

for(int j =0 ; j < 10; j++)//最多存10个指令,不够后面再修改吧

{

if(strlen(info_rec[j])==0) //给空的地方存

{

strcpy(info_rec[j],thread_info->info);

break;

}

}

pthread_mutex_unlock(&rec_mutex);

}

}

}

void *get_info_rec(void *arg) //显示线程调用的函数

{

while(1)

{

pthread_mutex_lock(&rec_mutex);

if(strlen(info_rec[0])!=0)

{

printf("%s \n",info_rec[0]);

for(int i=0;i<9;i++)

{

strcpy(info_rec[i],info_rec[i+1]);

}

memset(info_rec[9],0,128);

}

pthread_mutex_unlock(&rec_mutex);

//sleep(1);

}

}

int main(void)

{

char info[100]; //发送的

char addr[20]; //发送目标地址

struct thread_senddata thread_info; //发送信息函数利用的信息结构体

char buffer[128]; //接受到的数据,要不要其实无所谓了,后面再修改吧

int sockfd;

thread_recdata thread_rec;

memset(info_rec,0,10*128);

/*线程所需变量*/

pthread_t thread[Num_Thread]; //存储线程的id

pthread_attr_t attr; //线程属性设置

int rc; //创建线程的返回值,检查是否创建成功

void *status;

/*创建UDP*/

sockfd = initudp();

if (sockfd==0)

{

printf("socket error!");

}

/*设置接受线程参数*/

thread_rec.sockfd = sockfd;

thread_rec.info = buffer;

/*创建线程*/

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);

rc = pthread_create(&thread[0], &attr ,recinfo,(void *)&thread_rec); //收数据

if (rc){

printf("Error:unable to create thread");

exit(-1);

}

rc = pthread_create(&thread[1], &attr ,get_info_rec,NULL); //显示数据

if (rc){

printf("Error:unable to create thread");

exit(-1);

}

/*设置发送的数据*/

strcpy(info,"$HAKQGS112233");

// strcpy(addr,"10.106.3.65");

strcpy(addr,"10.106.2.146");

thread_info.addr = addr;

thread_info.info = info;

thread_info.port = port_out;

thread_info.sockfd = sockfd;

while(1)

{

sendinfo(&thread_info);

sleep(1);

strcpy(info,"$HAYRZT030000");

sendinfo(&thread_info);

sleep(1);

strcpy(info,"$HAYRZT030001");

sendinfo(&thread_info);

sleep(1);

strcpy(info,"$HAYRZT030002");

sendinfo(&thread_info);

}

//删除属性,并等待其他线程

pthread_attr_destroy(&attr);

for(int i = 0 ;i < Num_Thread;i++)

{

rc = pthread_join(thread[i], &status);

if (rc){

printf("Error:unable to join");

exit(-1);

}

}

pthread_exit(NULL); //删除线程

return 1;

}

WALDM

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值