水平和边缘触发实战
? ? ? ? ? ? ?水平觸發:當被監控的文件描述符上有可讀寫的時間發生時,epoll_wait會通知處理程序去讀寫,如果你沒有讀寫完,下次epoll_wait就會再直通知你。
? ? ? ? ? ? ? 垂直觸發:當被監控的文件描述符上有可讀寫時間發生時,epoll_wait會通知處理程序去讀寫,如果你沒有讀寫玩,下次epoll_wait就不會在通知你。
直接看代碼,源地址代碼我略微改了一下:
代碼地址:http://blog.csdn.net/stpeace/article/details/73692958
水平觸發:ev.events = EPOLLIN? ? ? ? 垂直觸發: ev.events = EPOLLIN|EPOLLET;//垂直觸發?
服務端:
?
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <netinet/tcp.h> #include <sys/epoll.h>#define MAXLINE 4096 #define BACKLOG 100 int main() { int iListenSock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in addr; memset(&addr, 0, sizeof(addr));inet_aton("0.0.0.0", &addr.sin_addr); addr.sin_family = AF_INET; addr.sin_port = htons(8888); int iOpt = 1; setsockopt(iListenSock, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt)); // 標配 bind(iListenSock, (sockaddr*)&addr, sizeof(addr)); listen(iListenSock, BACKLOG); epoll_event ev; ev.data.fd = iListenSock; //ev.events = EPOLLIN|EPOLLET;//垂直觸發ev.events = EPOLLIN;//水平觸發 epoll_event events; int epollFD = epoll_create(BACKLOG + 1); // 告訴內核監測的數目, 返回的epollFD為epoll管理句柄 epoll_ctl(epollFD, EPOLL_CTL_ADD, iListenSock, &ev); // 將ev和對應的iListenSock添加到epoll句柄,用于被epollFD管理 while(1) { int timeoutMS = -1; // 永不超時 int nfds = epoll_wait(epollFD, &events, BACKLOG + 1, timeoutMS); // events和nfds是一對輸出值 printf("nfds is %d\n", nfds); if(events.data.fd == iListenSock) // 用于監聽客戶端連接的socket { int iConnSock = accept(iListenSock, NULL, NULL); if (iConnSock < 0) { continue; } ev.data.fd = iConnSock; //ev.events = EPOLLIN|EPOLLET;//垂直觸發ev.events = EPOLLIN;//水平觸發 epoll_ctl(epollFD, EPOLL_CTL_ADD, iConnSock, &ev); // 將ev和對應的iConnSock添加到epoll句柄,用于被epollFD管理 printf("new sock came, fd is %d\n", iConnSock); } else { int iConnSock = events.data.fd; // 用于通信的socket char szBuf[2] = {0}; //使得每次只讀一個字節的數據int recvLen = recv(iConnSock, szBuf, sizeof(szBuf) - 1, 0); if (recvLen > 0) { printf("recv data [%s] from fd [%d]\n", szBuf, iConnSock); } else if(0 == recvLen) { ev.data.fd = iConnSock; epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev); //刪除ev中對應的句柄close(iConnSock); } else { ev.data.fd = iConnSock; epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev);//刪除ev中對應的句柄 close(iConnSock); } } } close(epollFD); close(iListenSock); return 0; }客戶端:
?
?
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <error.h>int main() { char sendBuf[20]="1234567890"; int ret = 0;int sockClient = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr=inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8888); ret=connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); send(sockClient,sendBuf,strlen(sendBuf),0);getchar(); close(sockClient); return 0; }先運行服務端,再運行客戶端。服務端每次接受一個字節的數據,水平觸發的服務端結果如下:
?
?
[mapan@localhost IO]$ ./server nfds is 1 new sock came, fd is 5 nfds is 1 recv data [1] from fd [5] nfds is 1 recv data [2] from fd [5] nfds is 1 recv data [3] from fd [5] nfds is 1 recv data [4] from fd [5] nfds is 1 recv data [5] from fd [5] nfds is 1 recv data [6] from fd [5] nfds is 1 recv data [7] from fd [5] nfds is 1 recv data [8] from fd [5] nfds is 1 recv data [9] from fd [5] nfds is 1 recv data [0] from fd [5]?
服務端對客戶端發來數據分10次接收了,epoll_wait返回了10次也就接收了10次。
注釋代碼中的水平觸發那一行,解開對垂直觸發那行的注釋,客戶端不變,編譯運行。垂直觸發的服務端結果如下:
?
[mapan@localhost IO]$ ./server nfds is 1 new sock came, fd is 5 nfds is 1 recv data [1] from fd [5]?
垂直觸發只接收了客戶端發來的第一個字節,并沒有接收完,就不接收了。
還是代碼結果一目了然。
?
?
?
? ? ? ? ??
?
?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結