user-0 提问: epoll编程，困扰了我6年的问题！求讨论。

回复:
user: user-1
content: 引用 35 楼 赵4老师 的回复:[quote=引用 34 楼 这个人很懒，连昵称也没有 的回复:] [quote=引用 6 楼 赵4老师 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 你这样的回复有屁用。[/quote] 你这样的挖坟连屁用都不顶。[/quote]  既然要回答问题，就要给点实际的。这样的回答，讲真，只能算是灌水。

user: user-1
content: 引用 6 楼 赵4老师 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 你这样的回复有屁用。

user: user-2
content: 引用 34 楼 这个人很懒，连昵称也没有 的回复:[quote=引用 6 楼 赵4老师 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 你这样的回复有屁用。[/quote] 你这样的挖坟连屁用都不顶。

user: user-3
content: 楼主，请参考这位兄弟的经验。https://blog.csdn.net/linuxheik/article/details/73294658

user: user-4
content: 楼主你这个问题我昨天也遇到了，今天总算解了 一开始以为是EPOLLIN的时候没有处理完，后来想了很久才意识到accept的时候也要用循环读到EAGAIN为止 这个在网上大多数的epoll框架都没有这样写的

user: user-5
content: 引用 22 楼 leinchu 的回复:@yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1] 已经过期，麻烦再贴一份

user: user-0
content: 问题没有解决，这个问题太难了，先结贴，再开帖子吧。

user: user-0
content: 引用 27 楼 bluesen 的回复:[quote=引用 3 楼 caojinrong 的回复:] 用了epoll再用线程，好奇葩的做法！  et模式下，socket必须设置为异步，确保每次都将缓冲区的数据读尽，否则是不会进入下一次触发的，估计你的问题就出这了。  说的好！[/quote]  设置为非阻塞的了的，进程还是线程不会成为影响问题的关键吧？ 而且，我这个socket服务并非一问一答的方式，服务器和客户端都有可能主动下发数据

user: user-0
content: 引用 26 楼 yangyunzhao 的回复:[quote=引用 22 楼 leinchu 的回复:] @yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1] 提供一下makefile文件吧[/quote]   很简单，没makefile gcc -g -o client client.c -lpthread

user: user-6
content: 引用 3 楼 caojinrong 的回复:用了epoll再用线程，好奇葩的做法！  et模式下，socket必须设置为异步，确保每次都将缓冲区的数据读尽，否则是不会进入下一次触发的，估计你的问题就出这了。  说的好！

user: user-7
content: 引用 22 楼 leinchu 的回复:@yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1]我直接用的开源的nginx所以怎么压都没问题。

user: user-0
content: 里面有验证稳定性的源码

user: user-0
content: @yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1]

user: user-8
content: 引用 22 楼 leinchu 的回复:@yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1] 提供一下makefile文件吧

user: user-0
content: 引用 24 楼 pengzhixi 的回复:[quote=引用 22 楼 leinchu 的回复:] @yangyunzhao @user-9 @pengzhixi  我这里有一个测试socket服务稳定性的程序： http://share.weiyun.com/4dab6e653ec6ec94416e71013ef3c02f  centos 64位下编译的， 你们看看你们的socket服务能不能经得起这个程序24小时的考验。  用法 ./client 线程数 端口 [服务器ip、默认127.0.0.1]我直接用的开源的nginx所以怎么压都没问题。[/quote]  我服了

user: user-9
content: https://github.com/chenshuo/muduo 这个项目描述 epoll 很规范，自己照着写就好。  https://github.com/chenshuo/muduo/blob/master/muduo/net/Channel.cc

user: user-8
content: 学习一下，一直都用的libevent，没有仔细研究过epoll

user: user-7
content: epoll_ctl(epoll_fd, EPOLL_CTL_DEL, tmpChain->fd, tmpChain->evt) 是有  EPOLL_CTL_ADD 才有 EPOLL_CTL_DEL。就和new 和delete要对应

user: user-7
content: 假死？你没有关闭监听的fd就应该没什么问题吧

user: user-0
content: 我把关闭fd的代码改到主线程了，用了一个链表。然后这种不消失的fd减少了，一晚上有1000多个。  后来又加上了epoll_ctl(epoll_fd, EPOLL_CTL_DEL, tmpChain->fd, tmpChain->evt)  移除fd，这种不减少的fd就变得很少，几个小时只有几十个。但socket监听已经假死了：telnet过去，不断开也不能收发消息！    求大神赶紧出现！ 贴上一段代码（管理socket fd的）： addData 添加到链表，checkData检测断开的释放资源。    typedef struct f_client_data{ 	int server_sock;     int client_sock; 	int fd; 	char ip[20]; 	int port; 	double lastActiveTs; 	int idx0; 	int idx1; 	int createTs; 	struct epoll_event* evt; #ifdef CLOSE_IN_MAIN 	struct f_client_data *next; 	int server_fd; 	int needToBeClosed; #endif } final_client_data;  #ifdef CLOSE_IN_MAIN void addData(struct f_client_data* data){ 	if(tail!=NULL) 		tail->next = data; 	tail = data; 	data->next = NULL; 	data->server_fd = 0; 	data->needToBeClosed = 0; }  void checkData(){ 	tmpChain1 = NULL;//上一个非需要移除的 	tmpChain2 = NULL;//临时保存变量用于free 	tmpChain = head;//保存当前检查的位置 	head = NULL; 	while(1){ 		if(tmpChain!=NULL && tmpChain->next!=NULL){ 			//final_client_data* sock_data = head->cur; 			if(tmpChain->needToBeClosed){ #ifndef EXETIME_DETECT 				printf("[evt = %p\n", tmpChain->evt); #endif 				if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, tmpChain->fd, tmpChain->evt) < 0) 				{ 					//perror("epoll ctl del error."); 					printf("EPOLL_CTL_DEL error at: %d, fd=%d, error: %s\n",__LINE__, tmpChain->fd, errno>0?strerror(errno):"EPOLL_CTL_DEL failed"); 					delEpollCountError ++; 				} 				tmpChain->evt->data.ptr = 0; 				 				closeSocket(tmpChain->fd); #ifndef EXETIME_DETECT 				printf("C,client,%d\n",tmpChain->fd); #endif 				if(tmpChain->server_fd>0){ 					closeSocket(tmpChain->server_fd); #ifndef EXETIME_DETECT 					printf("C,server,%d\n",tmpChain->server_fd); #endif 				}  				if(tmpChain1 != NULL) 					tmpChain1->next = tmpChain->next;  				tmpChain2 = tmpChain; 				tmpChain = tmpChain->next; 				free(tmpChain2); #ifndef EXETIME_DETECT 				printf("]\n"); #endif 			}else{ 				if(head==NULL){ 					head = tmpChain; 				} 				tmpChain1 = tmpChain; 				tmpChain = tmpChain->next; 			} 		}else break; 	} 	if(head==NULL)  		head = tmpChain; } #endif