栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

epoll的边沿触发的多线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

epoll的边沿触发的多线程

服务器的并发本质上都一样,都是将创建连接、收发数据的功能分配给子线程;父线程仅负责while循环下进行检测

父进程

1、完成服务器的设置;
2、创建epoll树和监听的epoll实例;
3、完成while循环,并把参数传递给子进程。

int main()
{
	//完成线程锁的初始化
	pthread_mutex_init(&mutex,NULL);

    // 创建监听的lfd
    int lfd = socket(AF_INET, SOCK_STREAM, 0);

    // 定义服务器性质,并储存在sockaddr_in addr中;绑定。
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
	
	//开启监听
	listen(lfd, 128);

	//创建epoll树
	int epfd = epoll_create(100);

	//上锁
	pthread_mutex_lock(&mutex);
	
	//创建epoll实例以及实例的数组
	struct epoll_event ev;
	ev.events = EPOLLIN;  
	ev.data.fd = lfd;
	int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &ev);
	
	struct epoll_event evs[1024];
	int size = sizeof(evs) / sizeof(struct epoll_event);

	//开始循环
	while(1)
	{
	int num = epoll_wait(epfd, evs, size, -1);
	for(int i = 0; i < num; i++)
	{
		int curfd = evs[i].data.fd;
		if(curfd == lfd)
		{
			Info info;
			info.lfd = lfd;
			info.epfd = epfd;
			info.ev.events = EPOLLIN | EPOLLET;  
			info.ev.data.fd = curfd;
			
			pthread_t tid;
			pthread_create(&tid,NULL,acceptConn,&info);
			pthread_detach(tid);
		}
		else 
		{
			Info info;
			info.lfd = lfd;
			info.epfd = epfd;
			info.ev.events = EPOLLIN | EPOLLET;  
			info.ev.data.fd = curfd;
			
			pthread_t tid;
			pthread_create(&tid,NULL,Communication,&info);
			pthread_detach(tid);
		}
	}
}
	

子进程 监听子进程
typedef struct Info{
	int epfd; 
	int lfd;
	struct epoll_event ev;
}

---------------------------------------------------------------------------------------------
void* acceptConn(void *arg)
{
	Info* tmp = (Info*) arg;
	int fd = tmp->ev.data.fd;//取出监听的fd
	
	int cfd = accept(fd , NULL, NULL);

	tmp.ev.events = EPOLLIN | EPOLLET;  
	tmp.ev.data.fd = cfd;

	//获得flag信息并修改
	int flag = fcntl(cfd, F_GETFL);
	flag |= O_NONBLOCK;                                                        
	fcntl(cfd, F_SETFL, flag);

	pthread_mutex_lock(&mutex);
	int ret = epoll_ctl(tmp->epfd, EPOLL_CTL_ADD, cfd, &(tmp->ev));//该ev已经在外面写好了,并且随着info传进来了,可以直接使用
	pthread_mutex_unlock(&mutex);

	
}
读写子线程
void Communication(void *argv){
   // 处理通信的文件描述符
   // 接收数据
 			    int* info = (int*) argv;
                char buf[1024];
                memset(buf, 0, sizeof(buf));
                while(1)
                {
                int len = recv((info ->ev).data.fd, buf, sizeof(buf), 0);
                if(len == -1)
				{
					if(errno = EAGAIN) //头文件error.h
					{
						printf("数据读取完毕");
						send(info->lfd,buf,strlen(buf)+1,0);
                        epoll_ctl(info->epfd, EPOLL_CTL_DEL,(info>ev).data.fd, NULL);
                        close((info ->ev).data.fd);
                        break;
					}
					else
					{
						perror("recv error");
						break;
						//如果使用exit会退出全部线程
					}
				}
				}
}

注意:当打印buff里面的字符串时,如果结尾处没有"/0"容易导致末尾处的一个字节的乱码。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1003008.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号