epoll和select原理类似,都是把文件描述符交给linux内核来监听。 select是使用fd_set,每次监听都要把他拷贝到内核,对他进行修改,才知道那个fd需要通信。 而epoll内部是使用红黑树实现的。
int lfd=socket(…); bind绑定ip和端口 listen();
//初始化树的根节点 int root=epoll_create(int num树的初始节点个数,可以自行增长); //把lfd挂到树上 epoll_ctl(…);
struct epoll_event all[3000];//epoll把需要通信的fd放到这个数组中 while(1){ int epoll_wait(); for(int )//对all数组进行遍历{ 如果fd==lfd表示连接请求,accept,把客户端的fd挂到树上 否则就是客户端fd发送数据请求,进行业务逻辑。{ 如果通信完毕,还应该把这个客户端的fd从树上去取下来,再关闭客户端fd。 } } }
epoll的水平触发和边沿触发 水平触发: 只要read缓冲区有数据,就会触发,比如上次发了10个字节,而只读取了5个字节,还是会触发。 边沿触发: 只触发一次,比如上次发了十个字节,不管有没有读完,都不会再次触发。只有有新的数据过来才会触发。 边沿非阻塞触发: 边沿触发,因此在读的时候就要一次性读完,使用while()循环读取数据。但是文件描述符默认是阻塞的。最后一次读完之后就会一直阻塞。程序无法正常执行。所以必须把文件描述符设置为非阻塞。