把高电平看作文件描述符是可读或可写状态,低电平黑色表示不可读或不可写,epoll_wait
的水平触发就是蓝色的时候epoll_wait
就会被触发,而边缘触发就是红色的时候epoll_wait
会触发,且只会触发一次。比如,client_fd
在某时刻充入数据,epoll_wait
第一次检测到,水平、边缘都会触发,进程开始读数据,若数据没有读完。那么水平触发会在下一次运行到epoll_wait
的时候再触发一次,而边缘触发就不会。
水平触发下,可能会多次调用epoll_wait
导致效率低下。而边缘触发下,如果第一次触发没有读干净缓冲区,那么就只能等到下一次冲入数据才能触发epoll_wait
读出上一次的数据,所以在边缘触发下,必须一次将缓冲区的数据读干净。
方法就是在死循环里一直读client_fd
,但读完后read
系统调用会阻塞,所以要将client_fd
设置为非阻塞:
int flags = fcntl(client_fd, F_GETFL);//获取的cfd的标志位
flags |= O_NONBLOCK;
fcntl(client_fd,F_SETFL,flags);
当read
读非阻塞文件描述符读干净的时候,不会阻塞,而是返回-1并且把errno
设置为EAGAIN
,这时就可以跳出死循环。
while (1)
{
char buf[SIZE] = "";
int n = read(fd, buf, SIZE);
if (n < 0)
{
if (errno == EAGAIN)
{
printf("读完了\n");
break;
}
Close(fd);
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
perror("read");
return 1;
}
else if (0 == n) // 套接字关闭
{
printf("client close\n");
Close(fd);
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
break;
}
else
{
Write(STDOUT_FILENO, buf, SIZE);
Write(fd, buf, n);
}
}