epoll+线程池+信号量
来源:互联网 发布:空间主页图片网络错误 编辑:程序博客网 时间:2024/06/06 10:47
epoll+线程池+信号量
该程序是对上一篇程序进行简单的修改。主要改动如下:
1.创建了多个线程来模拟线程池处理客户端的效果,上个程序是只有一个线程处理客户端。
2.如果用到多个线程处理客户端,那就需要将条件变量锁pthread_cond_t改成信号量sem_t sem。这样多个线程才能同时处理多个客户端事件。
3.另外封装了两个函数epoll_add(int epollfd, int fd, int events) 和 acceptAll(int server)
如图:
示例代码
#include <semaphore.h>#include <pthread.h>#include<arpa/inet.h>#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include<sys/stat.h>#include<fcntl.h>#include <unistd.h>#include<sys/epoll.h>#include <list>using namespace std;void epoll_add(int epollfd, int fd, int events){ struct epoll_event ev; ev.data.fd = fd; ev.events = events; // 先尝试修改,如果修改失败,再进行add操作 if(epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &ev) == -1) epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);}// 所有有消息的socket文件描述符,由子线程对其进行处理list<int> socks;// 防止全局变量被多线程访问导致不一致的情况pthread_mutex_t mutex;// 用来等待条件成立// pthread_cond_t cond;sem_t sem;int epollfd;int quit = 0;void* thread_func(void* ptr){ while(1) { sem_wait(&sem); // 主线程叫我退出,并且我的任务处理完成了,就可以安全退出了 if(quit && socks.size() == 0) // 可以不加锁 break; pthread_mutex_lock(&mutex); // 获取一个有消息的socket文件描述符 int fd = *socks.begin(); socks.pop_front(); pthread_mutex_unlock(&mutex); // 保证数据都被读完了 while(1) { char buf[1024]; int ret = read(fd, buf, sizeof(buf)); if(ret > 0) { // 处理数据 printf("%s\n", buf); } else if(ret == 0) { close(fd); break; } else // <0 { if(errno == EAGAIN) // 数据已经被读完了,应该把oneshot属性去掉 { epoll_add(epollfd, fd, EPOLLIN|EPOLLONESHOT); } if(errno != EAGAIN) close(fd); break; } } }}int acceptAll(int server){ while(1) { int newfd = accept(server, NULL, NULL); if(newfd < 0 && errno == EAGAIN) break; set_nonblock(newfd); epoll_add(epollfd, newfd, EPOLLIN|EPOLLONESHOT); }}int main(){ // 创建服务器 int server = create_server(9988, "0.0.0.0", 250); epollfd = epoll_create(1024); // 创建epoll // 创建线程 pthread_mutex_init(&mutex, NULL); sem_init(&sem, 0, 0); pthread_t tid1; pthread_create(&tid1, NULL, thread_func, NULL); pthread_t tid2; pthread_create(&tid2, NULL, thread_func, NULL); pthread_t tid3; pthread_create(&tid3, NULL, thread_func, NULL); // 将服务器非阻塞,并且将其加入epoll集合 set_nonblock(server); // 非阻塞 epoll_add(epollfd, server, EPOLLIN); struct epoll_event ev_out[8]; while(1) { // 等待消息 int ret = epoll_wait(epollfd, ev_out, 8, 2000); if(ret > 0) { int i; for(i=0; i<ret; ++i) { int fd = ev_out[i].data.fd; if(fd == server) { acceptAll(fd); } else // 一个不是server的文件描符有消息 // 应该将它发送给线程去处理 { // 要不要加锁?肯定要的 pthread_mutex_lock(&mutex); socks.push_back(fd); pthread_mutex_unlock(&mutex); sem_post(&sem); } } } else if(ret == 0 || (ret < 0 && errno == EINTR)) { continue; } else { exit(1); } } quit = 1; sem_post(&sem); sem_post(&sem); sem_post(&sem); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); return 0;}
0 0
- epoll+线程池+信号量
- 线程池和信号量
- 线程池 信号量
- linux线程池epoll
- epoll+线程池
- epoll+线程池+数据库连接池
- epoll+进程池+线程池
- Linux线程池加上epoll
- epoll+线程池服务器Demo
- epoll与线程池实现
- 线程 信号量
- 线程-信号量
- 线程信号量
- epoll的一个demo,备忘(epoll+线程池)
- 转 epoll的一个demo(epoll+线程池)
- Android 线程池、信号量、Looper、缓存初探
- 基于信号量的统一线程池机制
- 前端服务器框架---EPOLL+线程池
- 访问权限控制
- [vim as ide]配置方法
- 设计模式系列之五:适配器模式
- Qt多线程的实现
- 秒杀系统架构优化思路
- epoll+线程池+信号量
- PAT A1100. Mars Numbers (20)
- js如何判断变量的数据类型?
- 配置apache,直接访问服务器不显示文件目录
- 第二章 寄存器
- PLSQL Trigger will execute even when there is a Foreign Key Constraint Error
- AngularJs最简单解决跨域问题jsonp案例
- Unreal Engine 4 —— 键位更换以及对应思考
- mysql 并行写数据导致重复的问题,加间隙锁解决