把高電平看作文件描述符是可讀或可寫狀態,低電平黑色表示不可讀或不可寫,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);
}
}